【问题标题】:Using P/Invoke on structs and pointers在结构和指针上使用 P/Invoke
【发布时间】:2013-07-07 04:40:09
【问题描述】:

我正在尝试使用 P/Invoke 调用第三方原生 DLL 中的一些函数。 但我不断收到 FatalExecutionEngine 错误。 可能我在数据编组方面犯了一些错误?

这是我尝试使用的原生函数:

__declspec(dllexport) void dw_mm_directional_spectrum_initialise(
    struct dw_mm_directional_spectrum_T* directional_spectrum
    , const enum dw_buoy_type_T buoy_type
    , const unsigned char status[ /* NULL || sample_count */ ]
    , const double v[ /* sample_count */ ]
    , const double n[ /* sample_count */ ]
    , const double w[ /* sample_count */ ]
    , const unsigned int sample_count);

这是通过指针返回的原生结构:

struct dw_mm_directional_spectrum_T{
    signed char error_code;
    double* c_vv;
    double* c_nn;
    double* c_ww;
    double* c_nw;
    double* q_vn;
    double* q_vw;
    unsigned short output_size;
    double fraction_of_segments_used;
    unsigned char* list_of_used_segments;
    unsigned short list_of_used_segments_size;
};

这是C#程序中的结构体定义:

[StructLayout(LayoutKind.Sequential)]
struct datawell{
    Byte error_code;
    double[] c_vv;
    double[] c_nn;
    double[] c_ww;
    double[] c_nw;
    double[] q_vn;
    double[] q_vw;
    ushort output_size;
    double fraction_of_segments_used;
    IntPtr list_of_used_segments;
    ushort list_of_used_segments_size;
};

我的 DLLimport 签名:

[DllImport("libwaves.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void dw_mm_directional_spectrum_initialise(
    out datawell dw,
    Byte buoy_type,
    Byte[] status,
    double[] v,
    double[] n,
    double[] w,
    ushort sample_count);

这就是我在 C# 程序中使用该函数的方式:

double[] vertical = new double[512]; 
double[] north = new double[512];
double[] west = new double[512];
Byte[] status = new Byte[512];
datawell dw_test = new datawell();
ushort cnt = 512;

//dummy data generation
for(int i=0;i<512;i++){
    status[i]=1;
    vertical[i]=i*1.0;
    north[i]=i*1.0;
    west[i]=i*1.0;
}

dw_mm_directional_spectrum_initialise(out dw_test,0,status, vertical, north,west,cnt);

任何帮助将不胜感激。

问候,

杰瑞

【问题讨论】:

    标签: c# api pinvoke dllimport


    【解决方案1】:

    list_of_used_segments 在 C 中定义为 unsigned char*,在 C# 中定义为 double[]

    【讨论】:

    • SLaks,感谢您的回答。我将类型更改为 IntPtr 但仍然是同样的错误。
    【解决方案2】:

    您不能将结构中包含的指针编组为 C# 数组。您需要将它们声明为IntPtr,然后自己编组它们。您需要 Marshal.Copy() 来完成该过程。

    我不确定内存所有权规则。大概是本机代码分配了结构中返回的数组?如果是这样,那么我猜你必须在完成结构后再次调用本机库,以便它可以释放数组。

    【讨论】:

    • 大卫感谢您的回答。你完全正确。有一个函数可以销毁分配的内存,它将返回的结构作为输入。在将数组声明为 IntPtrs 并对其进行编组后,它可以正常工作。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 2012-01-21
    相关资源
    最近更新 更多