none
C#: How to call a C++ function RRS feed

  • Question

  • Hi all,
    I have to call a C++ function which is in a C++ DLL.

    The function has this signature:

    void ProdottoMatriciale(const emxArray_real_T *A, const emxArray_real_T *B, emxArray_real_T *Res)
    {
    }
    
    

    where emxArray_real_T is

    typedef struct emxArray_real_T
    {
        real_T *data;
        int32_T *size;
        int32_T allocatedSize;
        int32_T numDimensions;
        boolean_T canFreeData;
    } emxArray_real_T;
    
    


    in C# I'm trying something like:

    [DllImport(@"C:\thedll", EntryPoint = "theentrypoint", CallingConvention = CallingConvention.StdCall)]
    public static extern void prodottoM(mytype* A, mytype* B, mytype* C);
    
    


    where mytype is:

    [StructLayout(LayoutKind.Sequential, Size = 1)]
        public unsafe struct mytype
        {
            public double* data;
            public int* size;
            public int allocatedSize;
            public int numDimensions;
            public bool canFreeData;
        }
    
    


    when I try to use run the code (i.e snipped):

                mytype b3 = new mytype();
                b3.allocatedSize = 1;
                b3.canFreeData = true;
                b3.numDimensions = 1;
                b3.data = &dataC;
                b3.size = &sizec;
                mytype* b13 = &b3;
    
                int aaaa = 0;
                unsafe
                {
                    Class1.prodottoM(b11, b12, b13);
    
                }
    


    (of course I define also b12, b13)

    I got the error (translated from my language):

    "Impossible to do the marshaling of parameter #1: the pointers cannot refer to structures for which as been executed the marshaling. Use ByRef"

    any help apreciated

     


    • Edited by FraCal Monday, December 12, 2011 6:07 PM
    • Moved by Leo Liu - MSFT Tuesday, December 13, 2011 7:03 AM Moved for better support. (From:Visual C# General)
    Monday, December 12, 2011 6:06 PM

Answers

  • Hey FraCal

    I have same problem. As I understand the issue you should do like this.

     

     

    
    
    [StructLayout(LayoutKind.Sequential, Size = 4)]
        public struct mytype
        {
            public Intptr data;
            public IntPtr size;
            public int allocatedSize;
            public int numDimensions;
            public bool canFreeData;
        }
    [DllImport(@"C:\thedll", EntryPoint = "theentrypoint", CallingConvention = CallingConvention.StdCall)]
    public static extern void prodottoM(ref mytype A, ref mytype B, ref mytype C);
    
    


    and you do not need unsafe statement. When called you can do this

     

    Class1.prodottoM(ref b11, ref b12, ref b13);
    
    But bear in mind that you can't asign values like this.

                b3.data = &dataC;
                b3.size = &sizec;

    You sould use marsheling.

     

    Hope this helps.

     


    • Edited by Saymon Rupar Tuesday, December 13, 2011 9:01 AM
    • Marked as answer by Paul Zhou Tuesday, December 20, 2011 5:35 AM
    Tuesday, December 13, 2011 8:59 AM
  • Saymon's suggestion is correct. And it is the common way that we P/Invoke with unmanaged assembly.

    Extension of "Marsheling":

    Firstly, you need to use Marshal.AllocHGlobal Method to allocate memory from the unmanaged memory of the process by using the specified number of bytes.  In your case, the specified size is size of dataC and sizec. Then use Marshal.Copy Method to copy data to an unmanaged memory pointer.

    Moreover, at last, don't forget to use Marshal.FreeHGlobal Method to free unmanaged memory.


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    • Marked as answer by Paul Zhou Tuesday, December 20, 2011 5:35 AM
    Wednesday, December 14, 2011 8:57 AM

All replies

  • Looks like it is looking for a Ref type.  Can you try with this?
    Class1.prodottoM(&b3, &b2, &b1)
     
    instead of another assignment variable mytype* b13 = &b3;
    
    

     


    --Krishna
    Monday, December 12, 2011 6:51 PM
  • Hey FraCal

    I have same problem. As I understand the issue you should do like this.

     

     

    
    
    [StructLayout(LayoutKind.Sequential, Size = 4)]
        public struct mytype
        {
            public Intptr data;
            public IntPtr size;
            public int allocatedSize;
            public int numDimensions;
            public bool canFreeData;
        }
    [DllImport(@"C:\thedll", EntryPoint = "theentrypoint", CallingConvention = CallingConvention.StdCall)]
    public static extern void prodottoM(ref mytype A, ref mytype B, ref mytype C);
    
    


    and you do not need unsafe statement. When called you can do this

     

    Class1.prodottoM(ref b11, ref b12, ref b13);
    
    But bear in mind that you can't asign values like this.

                b3.data = &dataC;
                b3.size = &sizec;

    You sould use marsheling.

     

    Hope this helps.

     


    • Edited by Saymon Rupar Tuesday, December 13, 2011 9:01 AM
    • Marked as answer by Paul Zhou Tuesday, December 20, 2011 5:35 AM
    Tuesday, December 13, 2011 8:59 AM
  • Saymon's suggestion is correct. And it is the common way that we P/Invoke with unmanaged assembly.

    Extension of "Marsheling":

    Firstly, you need to use Marshal.AllocHGlobal Method to allocate memory from the unmanaged memory of the process by using the specified number of bytes.  In your case, the specified size is size of dataC and sizec. Then use Marshal.Copy Method to copy data to an unmanaged memory pointer.

    Moreover, at last, don't forget to use Marshal.FreeHGlobal Method to free unmanaged memory.


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    • Marked as answer by Paul Zhou Tuesday, December 20, 2011 5:35 AM
    Wednesday, December 14, 2011 8:57 AM
  • Thanks all for the answers, we are documenting ourself about the info you gave me. It's the first time I'm doing such a thing and I'm not familiar with C++ so that's why I'm in trouble.

    I'll post other questions if I'll need to, or the code when we solved the problem

     

    Wednesday, December 14, 2011 9:37 AM
  • Hi,

     

    Has your issue been resolved? Would you mind letting us know the result of the suggestions?

     

    Now I will mark an answer, you can mark others that you think to be so useful to your issue.

    If you still have any questions about this issue, please feel free to let me know. We will continue to work with you on this issue.

     

    Have a nice day!


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Tuesday, December 20, 2011 5:35 AM