Click here to Skip to main content
15,886,519 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have a function in C++ dll with its return is 2-point, as follows:

C++
#include "stdafx.h"
#include <vector>
using namespace std;

double** _stdcall f(int *n)
    {
        vector<double> t;
        vector<double> X;
        int i=0, j=0;
        do
        {
            t.push_back(3*i-4);
            X.push_back(2*j);

            i++;
            j++;
        }
        while (i<15&&j<90);
        *n=i;

        double** ret = new double*[2];
        for (i=0;i<2;i++)
            ret[i]=new double[*n];
        for (i=0;i<*n;i++)
        {
            ret[0][i]=t[i];
            ret[1][i]=X[i];
        }
        return ret;
    }


Now, I declare this function in C# as follows:

C#
[DllImport("exDP.dll")]
public static extern IntPtr[] f(ref int n_);


Now, all of C# code as follows:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace pABC
{
    public partial class frmABC : Form
    {

        [DllImport("exDP.dll")]
        public static extern IntPtr[] f(ref int n_);


        public frmABC()
        {
            InitializeComponent();
        }

        private void cmdOK_Click(object sender, EventArgs e)
        {
                int n = 0, i;


                IntPtr[] ret = new IntPtr[2];
                ret = f(ref n);

                double[] t = new double[n];
                Marshal.Copy(ret[0], t, 0, n);
                double[] X = new double[n];
                Marshal.Copy(ret[1], X, 0, n);

                MessageBox.Show("X[0]= " + X[0].ToString());
        }

    }
}


I compile OK. When I run it, an error occurs at the line:

C#
ret = f(ref n);


That is: Cannot marshal 'return value': Invalid managed/unmanaged type combination.

How to fix it and get the results correctly. Thanks.
Posted

My experience is: never allocate memory in C++ to use it in C#. Allocate the memory in C# and fill it in C++.

you should redesign the interface.
C+
_stdcall int f(int *n, double*arr);//return code signals sucess/error


in C#
double[] arrDoubles = new double[4];
int rc = f((n,arrDoubles);
 
Share this answer
 
Comments
Andrewpeter 18-Aug-14 4:47am    
Thanks KarstenK, I will try your solution. Vote 5 for you.
Try to type the return value from f as a IntPtr instead of a IntPtr[], then marshal that return value to a IntPtr[], iterate over that and marshal each entry to a double[].

Change
C#
[DllImport("exDP.dll")]
public static extern IntPtr[] f(ref int n_);

to
C#
[DllImport("exDP.dll")]
public static extern IntPtr f(ref int n_);

Then read the values like this;
C#
int n = 0, i;
IntPtr ret = f(ref n);

List<double[]> doubleArrays = new List<double[]>();

IntPtr[] intPtrs = new IntPtr[2];
Marshal.Copy(ret, intPtrs, 0, 2);
for(int c = 0; c < intPtrs.Length; ++c) {
    double[] array = new double[n];
    Marshal.Copy(intPtrs[c], array, 0, n);
    doubleArrays.Add(array);
}

The IntPtr can hold a reference to anything, including the double** result from the C++ function.

Hope this helps,
Fredrik
 
Share this answer
 
Comments
Andrewpeter 18-Aug-14 4:46am    
Thanks Fedrik, it's great. Vote 5.
Fredrik Bornander 18-Aug-14 4:47am    
Glad I could help.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900