使用c#代码中的void *参数调用本机c ++函数

时间:2015-07-28 13:03:36

标签: c# c++ pinvoke

我有一个本机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异常。

  

调用PInvoke函数' Test!Test.Form1 :: getCameraFrame'具有   堆栈不平衡。这可能是因为托管PInvoke   签名与非托管目标签名不匹配。检查一下   调用约定和PInvoke签名匹配的参数   目标非托管签名。

更新 - 解决了

大卫和迈克尔给出了答案,我已经设法通过以下代码解决了我的问题

[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) - 我一定错过了那部分,所以,那是我的坏事。

我能够获取原始数据,但无法将其转换为位图(原始数据采用某种奇怪的格式),但这是另一个问题。

由于

2 个答案:

答案 0 :(得分:1)

我有以下工作代码:

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

希望它有所帮助。

答案 1 :(得分:0)

我这样声明:

[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#。