如何将数组从.Net传递给C?

我试图利用一个用C语言编写的开源库,将其包装并将其暴露给.Net。 无论如何,我不是C专家。

到目前为止,我已经设法从F#调用用C语言编写的演示代码。 我设法通过遵循本指南然后填写空白来实现这一目标。 我已经调整了C代码以期望传递给它的int,所以我至少可以从F#中获取标量值到C.但是没有返回值。

但使用数组要复杂得多。

我的C代码是

extern "C" { __declspec(dllexport) void DisplayHelloFromDLL(int i) { //printf("Hello from DLL !\n"); cout << "You gave me ... an int: " << i <n = n; data->m = m; data->P = csc_matrix(data->n, data->n, P_nnz, P_x, P_i, P_p); data->q = q; data->A = csc_matrix(data->m, data->n, A_nnz, A_x, A_i, A_p); data->l = l; data->u = u; // Define Solver settings as default osqp_set_default_settings(settings); // Setup workspace work = osqp_setup(data, settings); // Solve Problem osqp_solve(work); // Clean workspace osqp_cleanup(work); c_free(data->A); c_free(data->P); c_free(data); c_free(settings); } } 

我的C#代码是

 class Program { [DllImport("TestLibCpp.dll")] public static extern void DisplayHelloFromDLL(int i); static void Main(string[] args) { Console.WriteLine("This is F# program"); DisplayHelloFromDLL(52); } } 

为了使这个问题的重点更加狭窄:如何使P_x成为一个参数,从F#传入?

在阅读了AlexF的链接并开始工作之后,我想我会在这里为有类似问题的人发布一个答案。 我可能会得到一些错误的概念,但代码可行。 如果我得到任何细节错误,请告诉我,我会编辑。

要注意的概念:Blittable类型:这些类型在.Net(托管)和C(非托管)中具有相同的内部表示。 Blittable类型由封送器“固定”,这似乎意味着指针从.Net传递到C,而不是被复制的值。 Blittable类型的内存位置将被锁定,直到非托管函数返回。 不确定这会如何影响垃圾收集。

输入/输出属性:Blittable数组作为In参数传递。 如果要将它们用作返回值,则必须将它们明确标记为Out。

无论如何,这是有效的代码。

非网管:

 extern "C" { __declspec(dllexport) void DisplayHelloFromDLL(c_float* P_x) { //printf("Hello from DLL !\n"); //cout << "You gave me ... an int: " << i << endl; // Load problem data //c_float P_x[4] = { 4., 1., 1., 2., }; //covariance matrix c_int P_nnz = 4; //number of non-zero elements in covar c_int P_i[4] = { 0, 1, 0, 1, }; //row indices? c_int P_p[3] = { 0, 2, 4}; //? c_float q[2] = { 1., 1., }; //linear terms c_float A_x[4] = { 1., 1., 1., 1., }; //constraint coefficients matrix c_int A_nnz = 4; //number of non zero elements in constraints matrix c_int A_i[4] = { 0, 1, 0, 2, }; //row indices? c_int A_p[3] = { 0, 2, 4}; //? c_float l[3] = { 1., 0., 0., }; //lower bounds c_float u[3] = { 1., 0.7, 0.7, }; //upper bounds c_int n = 2; //number of variables (x) c_int m = 3; //number of constraints // Problem settings OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings)); // Structures OSQPWorkspace *work; // Workspace OSQPData *data; // OSQPData // Populate data data = (OSQPData *)c_malloc(sizeof(OSQPData)); data->n = n; data->m = m; data->P = csc_matrix(data->n, data->n, P_nnz, P_x, P_i, P_p); data->q = q; data->A = csc_matrix(data->m, data->n, A_nnz, A_x, A_i, A_p); data->l = l; data->u = u; // Define Solver settings as default osqp_set_default_settings(settings); // Setup workspace work = osqp_setup(data, settings); // Solve Problem osqp_solve(work); // Clean workspace osqp_cleanup(work); c_free(data->A); c_free(data->P); c_free(data); c_free(settings); } } 

管理(F#)

 open System.Runtime.InteropServices module ExternalFunctions = [] extern void DisplayHelloFromDLL(float[] i) [] let main argv = let P_x = [|4.; 1.; 1.; 2.|] ExternalFunctions.DisplayHelloFromDLL(P_x); 0 // return an integer exit code