我需要从C DLL导出功能。这是我写的例子
typedef struct tag_struct {
unsigned char first;
unsigned char second;
} st_struct;
__declspec(dllexport) unsigned char Func( st_struct *ptr )
{
return ptr->first + ptr->second;
}
这是我用来导入上述功能的C#代码。
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ImportTest
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public class st_struct
{
public byte first;
public byte second;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
st_struct x = new st_struct();
x.first = 1;
x.second = 2;
byte result = Func(ref x);
}
[DllImport("MarshalTest.dll")]
protected static extern byte Func(ref st_struct inputs);
}
}
我的问题是Func的返回值不是3,应该是(1 + 2)。
我正在使用调试器查看DLL中的值-它们是不同的(不是我提供的1和2)。
当我像这样更改C#代码时,函数返回正确的值:
public Form1()
{
InitializeComponent();
st_struct x = new st_struct();
x.first = 1;
x.second = 2;
byte result = Func(x);
}
[DllImport("MarshalTest.dll")]
protected static extern byte Func(st_struct inputs);
当我删除参考时,问题消失了。但是我不明白为什么。
你能解释一下吗?
最佳答案
正如@kennyzx所提到的,由于您的st_struct
是一个类,因此它已经是引用类型,并将作为指针传递。我怀疑在其上抛出ref
会给你一个双指针,这在混合托管和非托管代码时没有多大意义。如果指针发生变化,编组器可能会处理该问题并为您创建一个新对象,但这似乎是一件很粗略的事情。
因此,当传递不带ref
的类时,它会按预期工作(C代码获取一个指针)。如果将其更改为struct
,则在不使用ref
的情况下传递它应该将其传递到堆栈上,而在使用ref
的条件下传递它将作为指针传递。
在您的情况下,使用struct
似乎是显而易见的选择,因为它可以直接传递(CLR只需将其固定并传递一个指针)即可。我怀疑使用class
会涉及更多的编组。
关于c# - 如何正确地将结构指针从C#传递到C DLL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31702766/