如何使用 C# 语言中的纯 C 库函数的 extern 调用将具有值的结构传递给它,并在返回值中获得相同的结构?
C#中的函数和结构:
public struct Structure
{
public int a;
public char c;
public string s;
public double d;
public float f;
}
[DllImport("lib")]
public static extern Structure entry (Structure s);
在 C# 代码中调用:
var s = entry(
new Structure
{
a = 1,
c = 'c',
f = 2,
d = 3,
s = "abc"
}
);
访问入口方法时抛出异常:
发生异常:CLR/System.AccessViolationException System.Private.CoreLib.dll 中发生“System.AccessViolationException”类型的未处理异常:“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
C中的lib库代码:
struct Structure
{
int a;
char c;
float f;
double d;
char * s;
};
struct Structure entry(struct Structure x);
struct Structure entry(struct Structure x)
{
struct Structure r = x;
return r;
}
void main()
{
}
库构建命令:
gcc -o lib -s -shared -Ofast lib.c -m64
我将 lib 文件放入/bin/Debug/net5.0/并运行 C# 方法。
2021 年 9 月 20 日更新
lib.c 库代码:
#include <uchar.h>
struct Structure
{
int a;
char c;
float f;
double d;
int * m;
char16_t * s;
};
struct Structure entry(struct Structure x);
struct Structure entry(struct Structure x)
{
struct Structure r = x;
short unsigned int t[6] = {1,2,3,4,5,6};
int t1[2] = {1,0};
r.s=(short unsigned int *)t;
r.m = (int*)t1;
return r;
}
void main()
{
}
C#代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Structure
{
public int a;
public char c;
public double d;
public float f;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public int[] m;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string s;
}
[DllImport("lib")]
public static extern Structure entry(Structure s);
C#调用代码:
var s = entry(new Structure { a = 1, c = 'c', f = 2, d = 3, m = new int[] { 5, 7 }, s = "UTF-16" });
结果不正确:
sm[0] = 5; sm[1] = 随机结果;ss = 随机结果。
在同事的评论之后,我发布了完整的答案。该代码在 Linux x64 和 .NET 5 中进行了测试。简化的库构建命令:
选项1
lib.c 代码
C# 声明代码
C#调用代码
选项 2
lib.c 代码
C# 声明代码
C#调用代码
有趣的是,可以从 C 程序返回长度更小的字符串,但不能返回大于 SizeConst 的字符串——它将被截断。