gpt4 book ai didi

c# - 从 C# 调用 C++ 函数,参数是接口(interface)指针

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:42:52 25 4
gpt4 key购买 nike

我有一个 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++ 函数,但是指针让我很难过。

如有任何帮助,我们将不胜感激!

我的解决方案

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);
}

C#代码

[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# 中,您应该告诉运行时您将委托(delegate)作为 C 函数指针传递。默认值很复杂,有时它会将这些委托(delegate)作为一些 COM 对象传递:

[DllImport("MyCPlusPlusDLLName", CallingConvention = CallingConvention.Cdecl)]
public static extern void initEx(
[In, MarshalAs( UnmanagedType.FunctionPtr )] MessageHandler callback);

最后,C# 运行时不知道您的 C++ 代码保留了该函数指针。 C 函数指针是非常简单的东西,没有办法引用它们。您的 C# 委托(delegate)将在 initEx 调用后不久被垃圾回收。发生这种情况时,您的代码将导致下一个 OnMessage 调用崩溃,调用一个已解除分配的对象。您需要将 handler 存储在某处,例如在静态变量中,因此 GC 将不理会它。

附言如果您仅以一种方式传递该消息,最好在 C++ 中指定 const Message*,在 C# 中指定 [In] ref Message。这将略微提高性能,编码器将停止将该结构从 C# 编码回 C++。

关于c# - 从 C# 调用 C++ 函数,参数是接口(interface)指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46033142/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com