gpt4 book ai didi

c# - 在结构中使用 boolean 值的一些 P/Invoke C# 到 C 编码问题

转载 作者:行者123 更新时间:2023-12-03 19:19:45 30 4
gpt4 key购买 nike

我在处理 boolean 类型以及在 C# 和 C 之间来回编码结构时遇到一些问题。我对 C 很生疏,但希望这部分没有什么严重错误。

据我所读/所见,.NET Boolean 和C# bool 类型为 4 个字节长,而C 类型 bool 仅 1 个字节。由于内存占用的原因,我不知道在 C 代码中使用定义的 BOOL 4 字节版本

这是一些简单的测试代码,希望能让我的问题清楚:


C 代码:

typedef struct
{
double SomeDouble1;
double SomeDouble2;
int SomeInteger;
bool SomeBool1;
bool SomeBool2;
} TestStruct;

extern "C" __declspec(dllexport) TestStruct* __stdcall TestGetBackStruct(TestStruct* structs);

__declspec(dllexport) TestStruct* __stdcall TestGetBackStruct(TestStruct* structs)
{
return structs;
}

我使用以下定义在 C# 中调用此代码:

    [StructLayout(LayoutKind.Explicit)]
public struct TestStruct
{
[FieldOffset(0)]
public double SomeDouble1;
[FieldOffset(8)]
public double SomeDouble2;

[FieldOffset(16)]
public int SomeInteger;

[FieldOffset(17), MarshalAs(UnmanagedType.I1)]
public bool SomeBool1;
[FieldOffset(18), MarshalAs(UnmanagedType.I1)]
public bool SomeBool2;
};

[DllImport("Front.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr TestGetBackStruct([MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] TestStruct[] structs);

这是 C# 中的实际测试函数:

    [Test]
public void Test_CheckStructParsing()
{
var theStruct = new TestStruct();
theStruct.SomeDouble1 = 1.1;
theStruct.SomeDouble2 = 1.2;
theStruct.SomeInteger = 1;
theStruct.SomeBool1 = true;
theStruct.SomeBool2 = false;

var structs = new TestStruct[] { theStruct };

IntPtr ptr = TestGetBackStruct(structs);

var resultStruct = (TestStruct)Marshal.PtrToStructure(ptr, typeof(TestStruct));
}

这在某种意义上是有效的,我确实得到了一个结构(使用调试器来检查它),但值完全错误。 IE。编码根本不起作用。我尝试了不同版本的 C# 结构,但没有成功。这是我的问题(1 和 2 最重要):

  1. C 函数是否适合此目的?
  2. 如何正确编写结构体,以便将结构体中的正确值返回到 C#?(是否有必要使用 StructLayout(LayoutKind.Explicit) 定义结构体属性使用 FieldOffset 值还是我可以使用 StructLayout(LayoutKind.Sequential) 代替)?
  3. 由于我在 C 中返回一个指向 TestStruct 的指针,因此我想应该可以在 C# 中返回 TestStructs 数组。但这似乎无法使用 Marshal.PtrToStructure 函数实现。是否可以通过其他方式实现?
  4. 显然,可以通过使用相同的 FieldOffset 属性值让多个结构体字段指向相同的内存分配,从而使用 C 中称为“union ”的东西。我理解这一点,但我仍然还不知道这种情况何时有用。请赐教。
  5. 有人可以推荐一本关于 C# P/Invoke to C/C++ 的好书吗? 我有点厌倦了在网络上到处获取信息。

非常感谢您对这些问题的帮助。我希望他们不要太多。

最佳答案

停止使用 LayoutKind.Explicit 并删除 FieldOffset 属性,您的代码将正常工作。您的偏移量未正确对齐字段。

public struct TestStruct
{
public double SomeDouble1;
public double SomeDouble2;
public int SomeInteger;
[MarshalAs(UnmanagedType.I1)]
public bool SomeBool1;
[MarshalAs(UnmanagedType.I1)]
public bool SomeBool2;
};

在 C# 中声明该函数,如下所示:

public static extern void TestGetBackStruct(TestStruct[] structs);

默认编码将与您的 C++ 声明匹配(您的代码实际上是 C++ 而不是 C),但您必须确保在调用函数之前在 C# 代码中分配 TestStruct[] 参数。通常,您还会将数组的长度作为参数传递,以便 C++ 代码知道有多少个结构。

请不要尝试从函数返回结构数组。使用 structs 参数作为输入/输出参数。

据我所知,没有一本书强调 P/Invoke。这似乎是一种黑魔法!

关于c# - 在结构中使用 boolean 值的一些 P/Invoke C# 到 C 编码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6612030/

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