且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将字符串从非托管代码传递给托管

更新时间:2023-02-12 16:29:25

您在调用约定上不匹配. C ++代码中的typedef声明具有默认调用约定__cdecl的函数指针.但是托管代码中的委托的默认值为__stdcall.

You have a mismatch on the calling convention. The typedef in your C++ code declares a function pointer with the default calling convention, which is __cdecl. But the default for a delegate in managed code is __stdcall.

否则,您将需要一个属性来告诉拼字游戏"编组.使它看起来像这样:

You will need an attribute to tell the pinvoke marshaller otherwise. Make that look like this:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void TestDelegate(string info);

在函数声明中放置[MarshalAs].如果可以的话,***在C ++代码中修复typedef,显然,使所有内容保持一致是首选的解决方案:

Drop the [MarshalAs] in the function declaration. Fixing the typedef in your C++ code might be preferable, if you can, clearly making everything consistent is the preferred solution:

    typedef void (__stdcall * TESTCALLBACK_FUNCTION )(char* msg);


无关,这是您需要修复的错误:


Unrelated, this a bug you'll need to fix:

   unmanaged.put_TestCallBack(new TestDelegate(this.Test));

您创建的委托对象对垃圾收集器不可见.如果将在下一个GC上收集,则当本机代码进行回调时,您的代码将崩溃.您必须将委托对象存储在某个地方,以便GC始终可以看到引用.要么作为类中的字段,还要求类对象必须保持足够长的生存期,要么作为静态变量.

The delegate object you create is not visible to the garbage collector. If will be collected on the next GC, your code will crash when the native code makes the callback. You have to store the delegate object somewhere so the GC always sees a reference. Either as a field in the class, with the additional requirement that the class object needs to stay alive long enough, or in a static variable.

请注意,当您声明回调接口而不是委托时,所有这些问题如何消失. COM方式.

Note how all of these problems disappear when you declare a callback interface instead of a delegate. The COM way.