CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Feb 2001
    Posts
    872

    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.

  2. #2
    Join Date
    May 2009
    Location
    Bengaluru, India
    Posts
    460

    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.

  3. #3
    Join Date
    Feb 2001
    Posts
    872

    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.

  4. #4
    Join Date
    May 2009
    Location
    Bengaluru, India
    Posts
    460

    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 !

  5. #5
    Join Date
    Feb 2001
    Posts
    872

    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.

  6. #6
    Join Date
    May 2009
    Location
    Bengaluru, India
    Posts
    460

    Talking Re: Passing multi-dimensional array from C# to Win32 C++ dll?

    Quote Originally Posted by THY02K View Post
    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];

  7. #7
    Join Date
    Feb 2001
    Posts
    872

    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

  8. #8
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    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
  •  





Click Here to Expand Forum to Full Width

Featured