从 c# 代码调用带有 void * 参数的本机 c++ 函数
Calling native c++ function with void *parameter from c# code
我有一个必须从我的 C# 代码调用的本机 C++ 函数,C++ 函数如下所示:
__declspec(dllexport) int getCameraFrame(void *buffer);
在 C++ 中调用函数如下所示:
unsigned char* data = new unsigned char[640 * 480 * 4];
getCameraFrame(data);
在 C# 中,我使用 PInvoke 将函数导入为:
[DllImport("CameraSDK.dll")]
public static extern int getCameraFrame(???);
我在这里使用什么作为参数,我如何从我的 C# 代码中调用该函数?
byte[] buffer;
getCameraFrame(out buffer); //???
更新
我尝试过使用 string、byte[]、char[]、IntPtr 作为参数,但我一直收到 PInvokeStackImbalance 异常。
A call to PInvoke function 'Test!Test.Form1::getCameraFrame' has
unbalanced the stack. This is likely because the managed PInvoke
signature does not match the unmanaged target signature. Check that
the calling convention and parameters of the PInvoke signature match
the target unmanaged signature.
更新 - 已解决
根据 David 和 Michael 给出的答案,我成功地使用以下代码解决了我的问题
[DllImport("CameraSDK.dll", CallingConvention.Cdecl)]
public static extern int getCameraFrame([Out] StringBuilder buffer);
StringBuilder data = new StringBuilder(1024 * 768 * 4)
int result = getCameraFrame(data);
大卫,你的回答确实是正确的,请注意我的 StringBuilder init 是 1024 * 768 * 4(而不是 640 * 480 * 4 - 这是抛出 AccessViolationException 的原因) - 在 C++ 代码中缓冲区被缩放从 (1024 * 768 * 4) 到 (640 * 480 * 4) - 我一定错过了那部分,所以,那是我的错。
我能够获取原始数据,但无法将其转换为位图(原始数据采用某种奇怪的格式),但这是另一个问题。
谢谢
我有以下工作代码:
C++ 定义:
__declspec(dllexport) void SendRenderedImage(byte buffer[]);
C# 声明
[DllImport("External.dll", EntryPoint = "SendRenderedImage", CallingConvention = CallingConvention.Cdecl)]
public static extern void SendRenderedImage(
[MarshalAs(UnmanagedType.LPArray)] byte[] buffer
);
C# 用法:
SendRenderedImage(new byte[10]);
希望对您有所帮助。
我会这样声明:
[DllImport(dllname, CallingConvention = ???)]
public static extern int getCameraFrame(
[Out] byte[] buffer
);
像这样调用函数:
byte[] data = new byte[640 * 480 * 4];
int retval = getCameraFrame(data);
请注意,您需要弄清楚调用约定是什么。从表面上看,它看起来像 cdecl。
我使用 [Out]
属性来指示数据从被调用方流向调用方。然而,由于编组器将简单地固定阵列,因此这没有明显的影响。它至少记录了未来读者的意图。
更新
您在评论中说您在使用此代码时遇到访问冲突鉴于您提供的信息,此处的代码是准确的。因此,问题一定出在我们看不到的地方。可能库还没有初始化。也许函数是实例方法。又或许还有其他的问题无法辨别。
您需要超越问题中显示的范围。如果我处在您的位置,我会首先制作一个使用该库的完整 C++ 程序,以证明该库可以正常工作并且您知道要进行的调用顺序。然后我会把它翻译成 C#。
我有一个必须从我的 C# 代码调用的本机 C++ 函数,C++ 函数如下所示:
__declspec(dllexport) int getCameraFrame(void *buffer);
在 C++ 中调用函数如下所示:
unsigned char* data = new unsigned char[640 * 480 * 4];
getCameraFrame(data);
在 C# 中,我使用 PInvoke 将函数导入为:
[DllImport("CameraSDK.dll")]
public static extern int getCameraFrame(???);
我在这里使用什么作为参数,我如何从我的 C# 代码中调用该函数?
byte[] buffer;
getCameraFrame(out buffer); //???
更新
我尝试过使用 string、byte[]、char[]、IntPtr 作为参数,但我一直收到 PInvokeStackImbalance 异常。
A call to PInvoke function 'Test!Test.Form1::getCameraFrame' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
更新 - 已解决
根据 David 和 Michael 给出的答案,我成功地使用以下代码解决了我的问题
[DllImport("CameraSDK.dll", CallingConvention.Cdecl)]
public static extern int getCameraFrame([Out] StringBuilder buffer);
StringBuilder data = new StringBuilder(1024 * 768 * 4)
int result = getCameraFrame(data);
大卫,你的回答确实是正确的,请注意我的 StringBuilder init 是 1024 * 768 * 4(而不是 640 * 480 * 4 - 这是抛出 AccessViolationException 的原因) - 在 C++ 代码中缓冲区被缩放从 (1024 * 768 * 4) 到 (640 * 480 * 4) - 我一定错过了那部分,所以,那是我的错。
我能够获取原始数据,但无法将其转换为位图(原始数据采用某种奇怪的格式),但这是另一个问题。
谢谢
我有以下工作代码:
C++ 定义:
__declspec(dllexport) void SendRenderedImage(byte buffer[]);
C# 声明
[DllImport("External.dll", EntryPoint = "SendRenderedImage", CallingConvention = CallingConvention.Cdecl)]
public static extern void SendRenderedImage(
[MarshalAs(UnmanagedType.LPArray)] byte[] buffer
);
C# 用法:
SendRenderedImage(new byte[10]);
希望对您有所帮助。
我会这样声明:
[DllImport(dllname, CallingConvention = ???)]
public static extern int getCameraFrame(
[Out] byte[] buffer
);
像这样调用函数:
byte[] data = new byte[640 * 480 * 4];
int retval = getCameraFrame(data);
请注意,您需要弄清楚调用约定是什么。从表面上看,它看起来像 cdecl。
我使用 [Out]
属性来指示数据从被调用方流向调用方。然而,由于编组器将简单地固定阵列,因此这没有明显的影响。它至少记录了未来读者的意图。
更新
您在评论中说您在使用此代码时遇到访问冲突鉴于您提供的信息,此处的代码是准确的。因此,问题一定出在我们看不到的地方。可能库还没有初始化。也许函数是实例方法。又或许还有其他的问题无法辨别。
您需要超越问题中显示的范围。如果我处在您的位置,我会首先制作一个使用该库的完整 C++ 程序,以证明该库可以正常工作并且您知道要进行的调用顺序。然后我会把它翻译成 C#。