gpt4 book ai didi

c# - 了解 C++ DLL 使用 union 映射到 C#

转载 作者:行者123 更新时间:2023-11-30 05:28:37 24 4
gpt4 key购买 nike

我有以下场景。我在用 C++ 编写的 DLL 中有一个带有 union 的结构,我需要将此结构映射到 C# 代码。请记住,我无法更改 DLL 中的代码。这是一个示例代码来说明正在发生的事情:

  typedef struct {
int type;
union {
int val;
double val2;
char *name;
};
} BIZARRE;

__declspec(dllexport) void changeBizarre(BIZARRE *bizarre, int type, const char *v)
{
bizarre->type = type;
if(type == 0) {
bizarre->val = 5;
} else if(type == 1) {
bizarre->val2 = 2.0;
} else if(type == 2) {
strncpy(bizarre->name, "test", strlen("test"));
} else if(type == 3 && strcmp(v, "test") == 0) {
bizarre->val = 10;
}
}

在 C# 代码中,我完成了以下操作:

[StructLayout(LayoutKind.Explicit)]
public unsafe struct BIZARRE
{
[FieldOffset(0)]
public int type;

[FieldOffset(8)]
public int val;

[FieldOffset(8)]
public double val2;

[FieldOffset(8)]
public char *name;
}

[DllImport("proj.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern void changeBizarre(ref BIZARRE bizarre, int type, char *name);

unsafe static void Main()
{
char[] v = "test".ToCharArray();
bizarre.type = 0;
bizarre.val = 0;
bizarre.val2 = 0.0;
fixed (char* address = v)
{
bizarre.name = address;
changeBizarre(ref bizarre, 3, &bizarre.name);
Console.WriteLine("{0}", bizarre.val);
}
Console.ReadKey();
}

现在,如果您通过传递 type = 2 来运行此代码,并尝试打印 bizarre.name,它将出现垃圾字符,如果您传递 type = 3,显然 DLL 无法获取指向的内容by bizarre.name,我相信这两种行为有相同的原因,但我不知道是什么原因。

最佳答案

char 数组并不是 C 中真正的 char 数组,实际上 C# 将使用 wchar_t 类型(16 位 char)。

使用 wchar_t 东西更改您的 C 代码:

typedef struct {
int type;
union {
int val;
double val2;
wchar_t *name;
};
} BIZARRE;

__declspec(dllexport) void changeBizarre(BIZARRE *bizarre, int type, const wchar_t *v)
{
bizarre->type = type;
if (type == 0) {
bizarre->val = 5;
}
else if (type == 1) {
bizarre->val2 = 2.0;
}
else if (type == 2) {
wcsncpy(bizarre->name, L"test", wcslen("test"));
}
else if (type == 3 && wcscmp(v, L"test") == 0) {
bizarre->val = 10;
}
}

或者

使用 byte 类型而不是 char 更改您的 C# 代码(如@Hans Passant 所述):

[StructLayout(LayoutKind.Explicit)]
public unsafe struct BIZARRE
{
[FieldOffset(0)]
public int type;

[FieldOffset(8)]
public int val;

[FieldOffset(8)]
public double val2;

[FieldOffset(8)]
public byte* name;
}


class Program
{

[DllImport("UnionMapping_dll.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern void changeBizarre(ref BIZARRE bizarre, int type, byte* name);

static unsafe void Main(string[] args)
{
BIZARRE bizarre;
byte[] v = Encoding.ASCII.GetBytes("test");
bizarre.type = 0;
bizarre.val = 0;
bizarre.val2 = 0.0;
fixed (byte* address = v)
{
bizarre.name = address;
changeBizarre(ref bizarre, 3, bizarre.name);
Console.WriteLine("{0}", bizarre.val);
}
Console.ReadKey();
}
}

关于c# - 了解 C++ DLL 使用 union 映射到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36745938/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com