-
July 29th, 2009, 09:05 PM
#1
Passing multi-dimensional array from C# to Win32 C++ dll?
hello
I'm trying to pass multi-dimensional arrays from C# to un-managed WIN32 C++ dll - second parameter of each of the two functions exported below are meant to be OUTPUT parameter (memory allocated in C# however)
Code:
MATLABGENERICDLL_API void GetCurves(char* strParam, double * myCurve)
{
for(int i=0; i<10; i++)
{
if(i>0) {
myCurve[i] = 1.01 * Curve[i-1];
} else {
myCurve[i] = 0.5;
}
}
return;
}
MATLABGENERICDLL_API void GetMatrix(char* strParam, double ** myMatrix)
{
try {
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
myMatrix[i][j] = 0.25;
}
}
} catch( ...)
{
throw;
}
return;
}
GetCurves executed successfully, but not GetMatrix.
Code:
class Program
{
[DllImport(@"C:\MatlabGenericDll.dll")]
private static extern string ToUpper2(string Src);
[DllImport(@"C:\MatlabGenericDll.dll")]
private static extern void GetCurves(string strParam, [In, Out] double[] myCurves);
[DllImport(@"C:\MatlabGenericDll.dll")]
private static extern void GetMatrix(string strParam, [In, Out] double[,] myMatrix);
static void Main(string[] args)
{
string strTest = "abc";
string strResult = null;
double[] myCurve = null;
double[,] myMatrix = null;
try
{
strResult = ToUpper2(strTest);
myCurve= new double[100];
GetYieldCurves("AAA", myCurve); << For some reason, executed succssfully (Although I checked &myCurve - address seems to be different in C#/C++ layer so I really don't understand why it worked)
myMatrix= new double[10, 10];
GetMatrix("BBB", myMatrix); << System.AccessViolationException, complained saying memory probably corrupted.
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return;
}
}
I'm not sure if I am doing right thing ... allocating memory from C# layer and if C# exe and C++ dll share same address space at all.
My end goal is: I actually also need to pass, from c# exe to unmanaged C++ dll, a two-dimensional array of undetermined size of different column types (string, doubles, int, DateTime)
Thanks!
http://msdn.microsoft.com/en-us/libr...53(VS.71).aspx
Last edited by THY02K; July 30th, 2009 at 01:01 AM.
-
July 29th, 2009, 11:26 PM
#2
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
Might be the memory you are allocating for the two dimensional array :
Code:
CorrelationMatrix = new double[10, 10];
if not enough and on the dll side it is causing error - though the code doesn't seem to tell though !.
anyways better you allocate more memory and try - like
Code:
CorrelationMatrix = new double[, ];
and also try setting the following attribute for the arrays - while calling the function in the dll
Code:
[In, Out] ref double[,]
Also one more thing I observed
Code:
YieldCurve = new double[100];
GetYieldCurves("AAA", myCurve);
CorrelationMatrix = new double[10, 10];
GetCorrelationMatrix("BBB", myMatrix);
Here you are allocating memory to YieldCurve and CorrelationMatrix variables and passing myCureve and myMatrix ?? Is it not giving you any compile erors for undeclared variables ??
You should be passing the variables for which you have allocated the memory.
-
July 30th, 2009, 12:49 AM
#3
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
hello
In my C# code, I've used the "ref" keyword:
Code:
[DllImport(@"C:\MatlabGenericDll.dll")]
private static extern void GetYieldCurves(string strStoredProcName, [In, Out] ref double[] YieldCurves);
[DllImport(@"C:\MatlabGenericDll.dll")]
private static extern void GetCorrelationMatrix(string strModelName, [In, Out] ref double[,] CorrelationMatrix);
...
static void Main(string[] args)
{
double[] YieldCurve = null;
double[,] CorrelationMatrix = null;
YieldCurve = new double[100];
GetYieldCurves("USD.L", ref YieldCurve);
CorrelationMatrix = new double[10, 10];
GetCorrelationMatrix("Basic", ref CorrelationMatrix);
return;
}
But still, after a couple of iterations from C++ / dll it still crahsed.
Code:
MATLABGENERICDLL_API void GetCorrelationMatrix(char* strModelName, double ** CorrelationMatrix)
{
try {
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
// Crashed after a few iterations
CorrelationMatrix[i][j] = 0.25;
}
}
} catch( ...)
{
throw;
}
return;
}
Also, address of "CorrelationMatrix " in C# not same in C++/dll. For example, from Watch Window:
Code:
In C#: &CorrelationMatrix 0x002cefa4 double[,]&*
In C++/dll: &CorrelationMatrix 0x002cedb0 double * * *
But I am using "ref" already... stack:
Code:
> MatlabGenericDll.dll!GetMatrix(char * strModelName=0x0021ef94, double * * Matrix=0x0021ef64) Line 68 C++
[External Code]
TestClient.exe!TestClient.Program.Main(string[] args = {string[0]}) Line 37 + 0xe bytes C#
[Frames below may be incorrect and/or missing, no symbols loaded for mscorwks.dll]
mscoree.dll!6d407c24()
kernel32.dll!75f04911()
ntdll.dll!774be4b6()
Last edited by THY02K; July 30th, 2009 at 01:04 AM.
-
July 30th, 2009, 04:27 AM
#4
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
what is size of double in C# ? what is the size of double data type in C++?
look at the difference , might be in C++ it is taking 8 bytes where as in C# it might be taking 4 bytes thats why the memory allocated by you on C# side might be less than what it is actually required on the C++/dll side - thats why it might be crashing !
-
July 30th, 2009, 05:48 AM
#5
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
Yes, this is why I allocated a 100x100 for a matrix when in C++ loop only traverse 10x10 matrix. But still it crashed.
-
July 30th, 2009, 05:59 AM
#6
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
Originally Posted by THY02K
Yes, this is why I allocated a 100x100 for a matrix when in C++ loop only traverse 10x10 matrix. But still it crashed.
But your code says 10*10
Code:
CorrelationMatrix = new double[10, 10];
-
July 30th, 2009, 06:01 AM
#7
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
yes but I also tried 100x100 just for sake of testing...
I was hoping perhaps if I allocate a big arce matrix from C# ... but it did not fix it
-
July 30th, 2009, 10:12 AM
#8
Re: Passing multi-dimensional array from C# to Win32 C++ dll?
you can always flatten the data structure.
Code:
public struct Foo {
public int[] A; // assuming a fixed size of 10
}
would look like:
Code:
public struct Foo {
public int A1;
public int A2;
public int A3;
public int A4;
public int A5;
public int A6;
public int A7;
public int A8;
public int A9;
public int A10;
}
its a bit more efficient than the array when marshaling it for interop. to deal with the ugliness of the object you could have a normal object that you work with in C# that will produce this data structure for you:
Code:
public class ManagedFoo {
List<int> items = new List<int>();
// ...
public Foo GetFooForInterop() {
Foo f;
f.A1 = items[0];
f.A2 = items[1];
// ...
f.A10 = items[9];
return f;
}
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|