0

我是 C++/CLI 的新手,在运行我的应用程序时遇到了一些问题。我有一个场景,非托管代码需要调用托管代码。我为此目的使用 GCHandle。这就是我的 CLI 类的样子

#pragma once
#include <msclr\gcroot.h>
#include "UnmanagedClass1.h"
using namespace System;

namespace Wrapper {
public ref class WrapperClass
{
private:
    UnmanagedClass::UnmanagedClass1* UnmanagedClass1obj;
    GCHandle delegateHandle_;



public:
    WrapperClass(void);
    delegate void EventDelegate(char *);
           EventDelegate^ nativeCallback_;
    void callback(char *msg);
 };
}

和cpp文件

using namespace Wrapper;

WrapperClass::WrapperClass(void)
{
UnmanagedClass1obj = new UnmanagedClass::UnmanagedClass1 ();

nativeCallback_ = gcnew EventDelegate(this, &WrapperClass::callback);

// As long as this handle is alive, the GC will not move or collect the delegate
// This is important, because moving or collecting invalidate the pointer
// that is passed to the native function below
delegateHandle_ = GCHandle::Alloc(nativeCallback_);

// This line will actually get the pointer that can be passed to
// native code
IntPtr ptr = Marshal::GetFunctionPointerForDelegate(nativeCallback_);

// Convert the pointer to the type required by the native code
UnmanagedClass1obj ->RegisterCallback( static_cast<EventCallback>(ptr.ToPointer()) );
   }

   void WrapperClass::callback(char *msg)
   {
//TDO
   }

我收到以下错误

error C2146: syntax error : missing ';' before identifier 'delegateHandle_' 
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   
error C4430: missing type specifier - int assumed. Note: C++ does not support 
error C2065: 'delegateHandle_' : undeclared identifier
error C2653: 'GCHandle' : is not a class or namespace name  
error C3861: 'Alloc': identifier not found  
error C2653: 'Marshal' : is not a class or namespace name   
error C3861: 'GetFunctionPointerForDelegate': identifier not found

前 3 个错误在 .h 文件中,其余在 cpp 文件中 我错过了一些库吗?

我还有一些关于实施的问题:

项目输出将是一个 dll。然后我如何使用它来实现与 c# 代码的回调。我的意思是我是否需要将 c# 类对象作为参考(如何?)或其他方式传递?

我正在使用 char 指针传回 C#。有更好的数据类型吗?例如 BSTR?谁来释放内存 C#、CLI、C++?

4

1 回答 1

0

我认为你只是做了包装器中最难的部分。现在,我将在包装器中创建一个事件以将消息发送给它的任何订阅者。让我给你看一个代码:H文件

// Define out custom delegate for event
public delegate void StringEventHandler(String^ /*msg*/);

ref class WrapperClass{
  // ... rest of class declaration ...
public:
   event StringEventHandler^ MyEvent;
  // ...
}

文件

// ... code
void WrapperClass::callback(char* msg)
{
   // Our method to marshal to String from char*
   String^ managedString = NativeString2ManagedString(char* msg);

   // Call the event delegate
   MyEvent(managedString);
}
// ... more code

我认为代码很清楚。可能是您的回调方法应该是私有成员,并且只是将 MyEvent 公开为公共成员。在 char* 和 String 之间编组,网上有很多例子;它取决于编码。要订阅事件,请创建一个与 StringEventHandler 签名相同的方法:

// c++/cli
wrapperClassInstance->MyEvent += gcnew StringEventHandler(obj, OtherClass::Method);
// c#
wrapperClassInstance.MyEvent += obj.Method;

我希望这对你有帮助。-- 杰罗 --

于 2013-08-26T11:38:18.473 回答