How to access this:
__declspec(dllexport) void __stdcall TestArray(int nI, int nJ, double** arr1, double** arr2)
{
int x1;
int x2;
for(x1 = 0; x1 < nI; x1++)
{
for(x2 = 0; x2 < nJ; x2++)
{
arr1[x1][x2] = 5;
arr2[x1][x2] = arr1[x1][x2];
}
}
return;
from c#
i tried with:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Runner
{
class Program
{
[DllImport("../../../debug/testArraysUnmanaged.dll")]
public static extern void TestArray(int i, int j, double[,] arr1, double[,] arr2);
static void Main(string[] args)
{
int nI = 100;
int nJ = 50;
double[,] array1 = new double[nI, nJ];
double[,] array2 = new double[nI, nJ];
TestArray(nI, nJ, array1, array2);
return;
}
}
}
but then I get "{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}"
is there any way to access ** array's in c from c#
thanks!

Marshaling unmanaged C 2D array
robear
Lucian thanks for the link I was there before but didn't get much help from that.
Miroslaw thanks for the response. If I can choose I would like to go for option 1 (would like to keep c code as is). I tried already this:
- send 2d array from c# with double[,] arr1
- that data is received in wrapper function in C which accepts double [] array
- in wrapper function make double** tempArr and copy data from double[] array to double** tempArr
- call original function with double** tempArr as param
and guess what happens Access Violation Exception.........
aaaaaaaaaaaaaaarrrrrgggggggghhhh
Any ideas
AKA13_Intrepid
const
int COL_DIM = 5;extern
"C" PINVOKELIB_API int TestMatrixOfInts( int pMatrix[][COL_DIM], int row );// Declares a managed prototype for a matrix of integers by value.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestMatrixOfInts([In, Out] int[,] pMatrix, int row );
// matrix ByVal
const int DIM = 5;
int[,] matrix = new int[ DIM, DIM ];
Console.WriteLine( "\n\nMatrix before call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
matrix[ i, j ] = j;
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}
int sum3 = LibWrap.TestMatrixOfInts( matrix, DIM );
Console.WriteLine( "\nSum of elements:" + sum3 );
Console.WriteLine( "\nMatrix after call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}
Jason D. Camp
double[,] arr1.
So you have to change the the C# declaration to
public static extern void TestArray (..., ref double[][] arr1, ...)
but jugged arrays are not supported by the marshaler.
In order to get it working you have two options
1. You have to marshal the arrays yourself to produce jugged arrays which results in unnecessary copy operations
2. Change the C function to accept double *array
insted of double **array. All other declaration have to be changed accordingly. The marshaler does support simple arrays. See the another answer to you question for references how to do it
kbromer
&#64;nt
if you declare in C the following double **array it is a jugged array with two
dimensionis. This means you have a pointer list of pointers to lists of of
values. By the intention of the code it happens that the lists of values are
all equally long.
Your example (copied from the msdn array marshaling demo) does not help here. It deals with two dimensional regular array a list of values logicaly partitioned in rows and columns. One would have to change the C function signature to accept double *array which is not the option here.
Perica
The simple solution is to allocate memory for the both the list on the first level and on the lists on the second level and copy the values accordingly. After the C call returns you must marshal the values back. I hope to helpt you.
Here is the code sample:
[DllImport("../../../debug/testArraysUnmanaged.dll")]
public static extern void TestArray(int i, int j, IntPtr arr1, IntPtr arr2);
private void doArray()
{
int nI = 3;
int nJ = 4;
double[][] array1 = new double[nI][];
double[][] array2 = new double[nI][];
for (int i = 0; i < nI; i++)
{
array1
array2
for (int j = 0; j < nJ; j++)
{
array1
array2
}
}
IntPtr pa1 = marshalJuggedToC(array1);
IntPtr pa2 = marshalJuggedToC(array2);
TestArray(nI, nJ, pa1, pa2);
array1 = marshalJuggedFromC(pa1, nI, nJ);
array2 = marshalJuggedFromC(pa2, nI, nJ);
for (int i = 0; i < array1.Length; i++)
for (int j = 0; j < array1
{
Console.WriteLine("arr1[{0}][{1}] = {2}", i, j, array1
Console.WriteLine("arr2[{0}][{1}] = {2}", i, j, array2
}
}
private IntPtr marshalJuggedToC(double[][] array)
{
int sizeofPtr = Marshal.SizeOf(typeof(IntPtr));
int sizeofDouble = Marshal.SizeOf(typeof(double));
IntPtr p1 = Marshal.AllocCoTaskMem(array.Length * sizeofPtr);
for (int i = 0; i < array.Length; i++)
{
IntPtr v1 = Marshal.AllocCoTaskMem(array
Marshal.Copy(array
Marshal.WriteIntPtr(p1, i * sizeofPtr, v1);
}
return p1;
}
private double[][] marshalJuggedFromC(IntPtr carray, int nI, int nJ)
{
int sizeofPtr = Marshal.SizeOf(typeof(IntPtr));
double[][] retval = new double[nI][];
for (int i = 0; i < retval.Length; i++)
{
retval
IntPtr v1 = Marshal.ReadIntPtr(carray, i * sizeofPtr);
Marshal.Copy(v1, retval
Marshal.FreeCoTaskMem(v1);
}
Marshal.FreeCoTaskMem(carray);
return retval;
}
Tom_Liu
Miroslaw,
This works great. I was trying something like this before but without WriteIntPtr and ReadIntPtr and ofcourse it was not working.
thanks for help!
grtz
Perica