在c#和DLL之间传递数组数据(两个方向)

本文关键字:方向 数据 两个 数组 DLL 之间 | 更新日期: 2023-09-27 17:50:35

我有一些编译成DLL的C代码。在c#中,我需要传递一个整型数组给它,并且我需要从中得到一个整型数组。

这是我目前所知道的。在c#中,唯一有效的函数是bar()。它返回22并按预期写入文件。其他代码正确地写入文件,但当控制权交还给c#时抛出异常。它读取,

"调用PInvoke函数'irhax!App::foo'使堆栈不平衡。这可能是因为托管的PInvoke签名与非托管的目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。"

C (DLL):
#define IG_API __declspec(dllexport)
IG_API void foo(int i) {
    FILE *f = fopen("foo.txt", "a+");
    fprintf(f, "%d'n", i);
    fclose(f);
}
IG_API int bar(void) {
    FILE *f = fopen("bar.txt", "a+");
    fprintf(f, "bar!'n");
    fclose(f);
    return 22;
}

IG_API void transmitIR(unsigned *data, int length) {
    FILE *f = fopen("transmit.txt", "a+");
    for(int i = 0; i < length; ++i)
        fprintf(f, "%d, ", data[i]);
    fprintf(f, "'n");
    fclose(f);
}
IG_API int receiveIR(unsigned *data, int length) {
    for(int i = 0; i < length; ++i)
        data[i] = 4;
    return length;
}
c#(调用者):
[DllImport("Plugin.dll")]
static extern void foo(int i);
[DllImport("Plugin.dll")]
static extern int bar();
[DllImport("Plugin.dll")]
static extern void transmitIR(uint[] data, int length);
[DllImport("Plugin.dll")]
static extern int receiveIR(out uint[] data, int length);

我很茫然。我做错了什么?因为我甚至不能让foo(int)工作,这似乎是一个很好的起点。

在c#和DLL之间传递数组数据(两个方向)

您的C代码使用cdecl调用约定。c#代码使用stdcall。

所有的DLLImport属性应该是:

[DllImport("Plugin.dll", CallingConvention=CallingConvention.Cdecl)]

当然,你也可以选择使用__stdcall将C代码转换为stdcall。但要确保你只做其中一件事!

receiveIR不需要out。你应该声明它:

static extern int receiveIR(uint[] data, int length);

你知道C函数的调用约定吗?就像错误所说的,这可能是一个不匹配。默认调用约定是stdcall,但如果这些函数使用cdecl约定,您可能会得到此错误。试着

[DllImport("Plugin.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void foo(int i);