C# 在结构和指针上使用P/Invoke

C# 在结构和指针上使用P/Invoke,c#,api,pinvoke,dllimport,C#,Api,Pinvoke,Dllimport,我正在尝试使用p/Invoke调用第三方本机DLL中的一些函数。 但我一直收到FatalExecutionEngine错误。 也许我在整理数据方面犯了一些错误,或者 这是我尝试使用的本机函数: __declspec(dllexport) void dw_mm_directional_spectrum_initialise( struct dw_mm_directional_spectrum_T* directional_spectrum , const enum dw_buoy_

我正在尝试使用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#程序中的结构定义:

我的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[]垂直=新的双精度[512];
double[]北=新的double[512];
double[]west=新的double[512];
字节[]状态=新字节[512];
数据井dw_测试=新数据井();
ushort-cnt=512;
//虚拟数据生成

对于(int i=0;i
list of_used_segments
在C中定义为
unsigned char*
,在C中定义为
double[]

list of_used_segments
在C中定义为
unsigned char*
,在C中定义为
double[]
在C#中。

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


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

您无法将结构中包含的指针封送为C#数组。您是g我需要将它们声明为
IntPtr
,然后自己封送它们。您需要
marshal.Copy()
才能执行该过程


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

SLaks,感谢您的回答。我将类型更改为IntPtr,但仍然是相同的错误或.SLaks,谢谢你的回答。我将类型更改为IntPtr,但仍然是相同的错误。David感谢你的回答。你完全正确。有一个函数可以销毁分配的内存,该内存将返回的结构作为输入。在将数组声明为IntPtr并封送后。复制它们时不会出现任何问题。非常感谢!D非常感谢您的回答。您完全正确。有一个函数可以销毁分配的内存,该内存将返回的结构作为输入。在将数组声明为INTPTR和封送处理后。复制它们时不会出现任何问题。非常感谢!
[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);
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);