是否有可能在名帅SAFEARRAY ref参数有可能、参数、SAFEARRAY、ref

2023-09-04 07:58:37 作者:青栀

下面是我的C#服务器方法:

Here is my C# server method:

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 ++客户端设置和调用此方法。这工作得很好,但是状态和输出变量不会出现被链接。就好像他们正在按值传递,而不是通过引用。

My C++ client is setting up and calling this method. This works fine, but the status and output variables don't appear to be chaining. It's as though they're being passed by value instead of by reference.

下面是我的客户code:

Here's my client code:

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参数,使'裁判'PARAMS复制回了援助?

Can someone provide assistance on setting up the SAFEARRAY arguments so that the 'ref' params are copied back out?

推荐答案

我可能不知道完整的答案,但我发现两件事情在你的code:

I might not know the full answer, but I spot two things in your code:

字符串没有被正确引用传递

在C#中字符串是不可变的参考对象。这意味着,对它们的引用被传来传去(按价值计算),而一旦被创建一个字符串,则不能进行修改。如果修改字符串值,您实际创建一个新的字符串,并更改本地引用它。

Strings in C# are immutable reference objects. This means that references to them are passed around (by value), and once a string is created, you cannot modify it. If you modify string value, you actually create a new string and change local reference to it.

有一个关于它很好的解释这里

There is a great explanation about it here

所以,你需要在你的C#函数的定义修改为这样的事情:

So, you need to change the definition of your C# function to something like this:

public void Exec(out int status, out string output)
{
    ...
}

您应该使用,而不是OUT REF

您似乎初始化参数值 C#函数调用之前不进的功能本身。

You seem to initialize argument values before C# function call not into function itself.

所以,你应该用裁判来代替了关键字;

So, you should use ref instead of out keyword;

public void Exec(ref int status, ref string output)
{
    ...
}