这是我的C#服务器方法:
public void Exec(out int status, string output)
{
status = 3;
Console.WriteLine("Exec({0}, ...)", status);
output = string.Format("Hello from .NET {0}", DateTime.Now);
Console.WriteLine("Exec(..., {0})", output);
}
我的C ++客户端正在设置并调用此方法。这工作正常,但状态和输出变量似乎不是链接。就好像它们是通过价值而不是通过参考传递的。
这是我的客户代码:
InitCLR();
LONG index = 0;
LONG i1 = 12; // just some number for testing
BSTR s1 = SysAllocString(L"Hello world");
SAFEARRAY* args = NULL;
CHECK_HRESULT( SafeArrayAllocDescriptor(1, &args) );
args->cbElements = sizeof(VARIANT);
args->rgsabound[0].lLbound = 0;
args->rgsabound[0].cElements = 2;
CHECK_HRESULT( SafeArrayAllocData(args) );
// byref not working for in/out param
VARIANT arg1;
VariantInit(&arg1);
V_I4REF(&arg1) = &i1;
V_VT(&arg1) = VT_I4 | VT_BYREF;
// byref not working
VARIANT arg2;
VariantInit(&arg2);
V_BSTR(&arg2) = SysAllocString(L"Hello world");
V_VT(&arg2) = VT_BSTR;
index = 0;
CHECK_HRESULT( SafeArrayPutElement(args, &index, &arg1) );
index = 1;
CHECK_HRESULT( SafeArrayPutElement(args, &index, &arg2) );
int bindingFlags = mscorlib::BindingFlags_InvokeMethod |
mscorlib::BindingFlags_Instance |
mscorlib::BindingFlags_Public;
VARIANT retval;
VariantInit(&retval);
bstr_t methodName("Exec");
HRESULT hRes = Type->InvokeMember_3(
methodName,
static_cast<mscorlib::BindingFlags>(bindingFlags),
NULL, // binder *
Instance,
args,
&retval);
_tprintf(TEXT("Exec() == 0x%x\n"), hRes);
_tprintf(TEXT("i1=%d\n"), i1);
有人可以提供有关设置SAFEARRAY参数的帮助,以便将'ref'参数复制回来吗?
答案 0 :(得分:0)
我可能不知道完整的答案,但我在你的代码中发现了两件事:
字符串未通过引用正确传递
C#中的字符串是不可变的引用对象。这意味着对它们的引用会传递(按值),一旦创建了一个字符串,就无法修改它。如果修改字符串值,实际上是创建一个新字符串并更改对它的本地引用。
有一个很好的解释here
因此,您需要将C#函数的定义更改为:
public void Exec(out int status, out string output)
{
...
}
您应该使用ref代替
您似乎在 C#函数调用之前初始化参数值而不是函数本身。
因此,您应该使用ref而不是out keyword;
public void Exec(ref int status, ref string output)
{
...
}