从 C# 调用 C 函数,传递包含指针的结构

Posted

技术标签:

【中文标题】从 C# 调用 C 函数,传递包含指针的结构【英文标题】:Calling C function from C#, passing struct which contains pointers 【发布时间】:2016-05-19 21:28:39 【问题描述】:

我需要通过 PInvoke 从 C# 调用 C 函数,将指针传递给结构,并且该结构也包含一个指针。

结构体可以在 C 中简化为,

struct myStruct 
  int myInt;
  float *myFloatPointer;

函数声明可以简化为

void myFunc(myStruct *a);

在 C# 中,我这样声明函数

[DllImport("my_library.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void myFunc(ref myStruct a);

不幸的是,我无法确定如何在存在指针参数的情况下在 C# 中声明结构。

C 函数不分配浮点指针指向的内存,它只是修改它。我宁愿在不使用 unsafe 关键字的情况下解决这个问题。

我已经使用 float[] 成功地通过带有 float* 参数的 PInvoke 调用了函数,但这似乎在这里不起作用。

提前致谢。

【问题讨论】:

我有一段时间没做c#了,但我相信unsafe关键字可以让你声明和使用指针 首先你需要弄清楚指针指向什么。标量?大批?谁分配?为什么要写呢? 那是 C++。这不是有效的 C。 How to pass a pointer from C# to native function in DLL?的可能重复 也看看这里:***.com/questions/20419415/… 【参考方案1】:

C 指针本质上是不安全的,但您无需在此处使用 unsafe 关键字,即使将使用底层概念。

您可以使用 IntPtr 声明结构:

struct myStruct

    public int myInt;
    public IntPtr myFloatPointer;

并在固定浮点数组后使用 Marshal 方法初始化字段:

    float[] data = new float[15];
    myStruct ms = new myStruct();

    GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
    ms.myFloatPointer = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);

这样,您就不会使用 unsafe 关键字。

请注意,根据您运行的平台,指针的大小及其对齐方式可能会有所不同;该结构可能需要一些特定的布局。

【讨论】:

以上是关于从 C# 调用 C 函数,传递包含指针的结构的主要内容,如果未能解决你的问题,请参考以下文章

C#调用C++的dll库怎么传递结构体中不定长度的char数组

如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它

c# 调用c dll void 指针类型转化问题

将 C++ 结构指针从 Perl 传递给任意 dll 函数调用

如何将指向 C# 结构的指针传递给 C 中的方法

C#如何调用C++的DLL的结构体数组指针