简体   繁体   English

从C返回数组到.Net:我在做什么错?

[英]Returning an array from C to .Net: What am I doing wrong?

This is a follow on from this question . 这是该问题的后续内容。

I am trying to return an array of floating point numbers from C, to .Net. 我试图将浮点数数组从C返回到.Net。 I will include some F# code, as well as C# code, so that people of either language can answer. 我将包括一些F#代码以及C#代码,以便两种语言的人都可以回答。

Unmanaged C code: 非托管C代码:

extern "C"
{
    __declspec(dllexport) void DisplayHelloFromDLL(c_float* P_x, c_float* 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);

        //return the value
        OSQPSolution* sol = work->solution;
        x = sol->x;

        // Clean workspace
        osqp_cleanup(work);
        c_free(data->A);
        c_free(data->P);
        c_free(data);
        c_free(settings);
    }
}

So all I have done is declared a parameter 'x', and I am setting it after the results are calculated. 因此,我所做的一切都被声明为参数“ x”,并在计算结果后对其进行设置。

F# code F#代码

open System.Runtime.InteropServices

module ExternalFunctions =
    [<DllImport("TestLibCpp.dll")>]
    extern void DisplayHelloFromDLL(float[] i, [<In>][<Out>] float[] x)

[<EntryPoint>]
let main argv = 
    let P_x = [|4.; 1.; 1.; 2.|]
    let mutable xResult:float[] = [|0.;0.|]
    ExternalFunctions.DisplayHelloFromDLL(P_x, xResult);

    printfn "This is x:%A" xResult
    0 // return an integer exit code

C# code C#代码

class Program
    {
        [DllImport("TestLibCpp.dll")]
        public static extern void DisplayHelloFromDLL(double[] i, [In, Out] double[] x);
        static void Main(string[] args)
        {
            Console.WriteLine("This is C# program");
            double[] P_x = new double[] {4.0, 1.0, 1.0, 2.0};
            double[] x = new double[] { 0.0, 0.0};
            DisplayHelloFromDLL(P_x, x);

            Console.WriteLine("Finished");
        }
    }

In both the F#, and C# cases, the value of x is unchanged. 在F#和C#情况下,x的值均不变。 I have tried other variations such as 我尝试了其他变体,例如

open System.Runtime.InteropServices

module ExternalFunctions =
    [<DllImport("TestLibCpp.dll")>]
    extern void DisplayHelloFromDLL(float[] i, [<In>][<Out>] float[]& x)

[<EntryPoint>]
let main argv = 
    let P_x = [|4.; 1.; 1.; 2.|]
    let mutable xResult:float[] = [|0.0; 0.0|]
    ExternalFunctions.DisplayHelloFromDLL(P_x, &xResult);

    printfn "This is x:%A" xResult

But I suspect the problem is the C code, not the .Net code. 但是我怀疑问题是C代码,而不是.Net代码。 I think the problem is that work->solution->x is a pointer, not an array. 我认为问题是work-> solution-> x是指针,而不是数组。 I am guessing that I need to convert it from a pointer to an array, but can't work out how to do that. 我猜想我需要将其从指针转换为数组,但无法解决该问题。 And again, not totally sure this is even the problem to begin with. 再说一次,也不完全确定这甚至是问题的开始。

Thanks to PetSerAl for pointing (pun intended) me in the right direction. 感谢PetSerAl向我指出(正确的双关语)正确的方向。

All I needed to do was change part of the C code to 我要做的就是将C代码的一部分更改为

        //return the value
        OSQPSolution* sol = work->solution;
        for (int i = 0; i != n; ++i)
            x[i] = sol->x[i];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM