[英]Call a C++ function from C# and the param is a interface pointer
我有一個C ++ DLL。 它包含以下功能:
struct Message {
int id;
unsigned short messageLength;
unsigned char* message;
};
class Listener {
public:
virtual void OnMessage(Message* message);
};
void init(Listener* listener);
有沒有辦法從C#調用函數“ init”? 我知道您可以在C#中使用[DllImport]來調用C ++函數,但是指針給我帶來了麻煩。
任何幫助,將不勝感激!
typedef void (*MessageHander)(Message* message);
class MessageDelegate : public Listener {
public:
MessageHander* messageCallback; // hold the callback funtion
virtual void OnMessage(Message* message) {
if (messageCallback) {
(*messageCallback)(message);
}
}
}
static MessageDelegate messageDelegate;
void initEx(MessageHander* handler) {
messageDelegate.messageCallback = handler;
init(messageDelegate);
}
[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Message {
public int id;
public ushort messageShort;
public IntPtr message;
}
class Program {
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MessageHandler(ref Message message);
[DllImport("MyCPlusPlusDLLName", CallingConvention = CallingConvention.Cdecl)]
public static extern void initEx(ref MessageHandler callback);
public void OnMessage(ref Message message) {
byte[] rawMessage = new byte[message.messageLength];
Marshal.Copy(message.message, rawMessage, 0, message.messageLength);
// some other logic
}
public void Run() {
MessageHandler handler = new MessageHandler(this.OnMessage);
initEx(ref handler);
}
}
您的代碼中有幾個問題。
在C ++中,您的MessageHander
已經是一個指向函數的指針。 無需指向指針的指針。 修正:
MessageHander messageCallback; // hold the callback function
messageCallback( message );
void initEx( MessageHander handler )
在C#中,應該告訴運行時您將委托作為C函數指針傳遞。 默認值很復雜,有時它會將這些委托作為一些COM對象傳遞:
[DllImport("MyCPlusPlusDLLName", CallingConvention = CallingConvention.Cdecl)]
public static extern void initEx(
[In, MarshalAs( UnmanagedType.FunctionPtr )] MessageHandler callback);
最后,C#運行時不知道您的C ++代碼保留了該函數指針。 C函數指針非常簡單,無法對其進行引用計數。 您的C#委托將在initEx調用后不久被垃圾回收。 發生這種情況時,您的代碼將使下一個OnMessage調用崩潰,從而調用一個已取消分配的對象。 您需要將handler
存儲在某個地方,例如,在一個靜態變量中,因此GC將不理會它。
PS:如果僅以一種方式傳遞該消息,則最好在C ++中指定const Message*
在C#中指定[In] ref Message
。 這將稍微提高性能,封送拆收器將停止將結構從C#編送回C ++。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.