C#编组C结构

时间:2017-04-06 13:29:01

标签: c# struct pinvoke dllimport

我已经使用了这个C-C#代码:

·H

typedef struct {

  float a;
  float b;

} MyStruct;

extern MyStruct mystruct;

__declspec(dllexport) void  GetMyStruct (MyStruct* s);
__declspec(dllexport) void  SetMyStruct (MyStruct* s);

.C

    MyStruct mystruct;

    void GetMyStruct (MyStruct* s)
    {

        *s = AeroLink_IOPkt;
    }

    void SetMyStruct (MyStruct* s)
    {

        AeroLink_IOPkt = *s; 
    }

void test()
{
   // some code that update element in struct
   // mystruct.a = 0.4;
   // mystruct.a = 0.1;
}

的.cs

public struct MyStruct
{

  public float a;
  public float b;

} 


[DllImport(DLL_NAME, EntryPoint = "GetMyStruct")]
protected static extern void GetMyStruct(ref MyStruct s);

[DllImport(DLL_NAME, EntryPoint = "SetMyStruct")]
protected static extern void SetMyStruct(ref MyStruct s);

这样,每当我需要将数据从C#设置为C时,我必须调用void SetMyStruct,反之亦然,如果我想从C(从void test更新)获取数据到C#我必须调用{ {1}}。我必须每秒做50次。

有没有办法避免每次都致电GetMyStructSetMyStruct?我想一次使用GetMyStruct,然后将所有更改反映出来。我不知道这是否可能。

1 个答案:

答案 0 :(得分:1)

您可以使用unsafe和指针执行此操作。

你需要编译你的C#程序"不安全"启用。

编辑:更好的方法:

向库中添加以下功能:

__declspec(dllexport) void  GetMyStructRef (MyStruct** s);
void GetMyStructRef(MyStruct** s)
{
    *s = &mystruct;
}

在C#中:

[DllImport(DLL_NAME, EntryPoint = "GetMyStructRef")]
protected static extern void GetMyStructRef(ref MyStruct* s);

MyStruct* data;
GetMyStructRef(ref data);
Console.WriteLine($"{data->a} {data->b}");

旧答案:

unsafe class MyClass : IDisposable
{
    [DllImport(DLL_NAME, EntryPoint = "GetMyStruct")]
    protected static extern void GetMyStruct(MyStruct* s);

    [DllImport(DLL_NAME, EntryPoint = "SetMyStruct")]
    protected static extern void SetMyStruct(MyStruct* s);

    GCHandle handle;
    MyStruct* structRef;

    public void MyClass()
    {
        //we need to get a pinned reference to your struct
        handle = GCHandle.Alloc(new MyStruct(), GCHandleType.Pinned);
        structRef = (MyStruct*)handle.AddrOfPinnedObject().ToPointer();

        SetMyStruct(structRef);
    }

    public void Dispose()
    {
        //We need to free the handle to release memory
        //GC will not collect it without this
        handle.Free();
    }
}