locked
Passing array from c# to c++ in interop RRS feed

  • Question

  • The DLL "OPC_AE.dll" is created by c++, and we create a "OpcAeInterop.dll" by ILDASM .

    There is a method named AskCondition(), its function protype in "OpcAeInterop.dll" is:

    void AckCondition(uint dwCount, string szAcknowledgerID, string szComment, ref string pszSource, ref string pszConditionName, ref ViewPoint.Server.Alarm._FILETIME pftActiveTime, ref uint pdwCookie, System.IntPtr ppErrors)

    There are many ref parameters in this function, actually each of them is array variable, it should be the address of array.

    I have tried use array directly in C#, like string[] strSource = new string[1]; and call AckCondition (ref strSource ),

    and got error "cannot convert from ref string[] to ref string".

    So my question is : how we can pass the array variable to AckCondition function in C# .net?

    Tuesday, November 26, 2013 9:27 AM

Answers

  • Now I have figure out the solution about this problem, my idea is right, edit the il file.

    General steps are:

    1. Use TlbImp to create the interop DLL file by "OPC_AE.dll"

    2. Use Ildasm to create il file by interop DLL file.

    3. Edit the il file, change the define content of "AckCondition".

    4. Use Ilasm to recreate interop DLL by the new il file.

    Anyway, thanks for all people reply to me ... So happy to fix it... *_*
    • Marked as answer by Razer518 Wednesday, December 4, 2013 12:44 AM
    Wednesday, December 4, 2013 12:43 AM

All replies

  • Hi,

       Use StringBuilder in c# for this type of PInvoke. For Example

    StringBuilder objBldr = new StringBuilder(255);

    AskCondition(ref objBldr);


    Thanks and Regards, vinothkumar.A

    Tuesday, November 26, 2013 12:25 PM
  • To pass such values, create the variable, initialize it, then use ref:

    string source = “some text”;
    uint cookie = 1234;

    AckCondition( . . ., ref source, . . ., ref cookie, . . .);



    • Edited by Viorel_MVP Wednesday, November 27, 2013 6:06 AM
    Tuesday, November 26, 2013 12:52 PM
  • Hi, Thanks for your reply.

    The AckCondition function needs the string array variable.

    So you mean the StringBuilder objBldr = new StringBuilder(255);

    objBldr.Add("Element1"); // First item.

    objBldr.Add("Element2"); //Second item.

    objBldr.Add("Element3"); //Third item.

    ...

    Then call AskCondition(ref objBldr);

    Am i right?

    Wednesday, November 27, 2013 2:35 AM
  • Hi, thanks for your reply.

    for the uint cookie = 1234; line it should be array of uint.

    I must define uint[] cookie = new uint[3];

    cookie[0] = 1;

    cookie[1] = 2;

    cookie[2] = 3;

    Then call AckCondition(ref cookie);? Is this right?

    Wednesday, November 27, 2013 2:40 AM
  • According to the prototype, cookie is not an array. If a function is “void AckCondition(ref uint cookie)”, then the call is:

        uint cookie = 1234;
        AckCondition(ref cookie).

    You need an array when the prototype is “void AckCondition(uint [] cookie)” or “void AckCondition(ref uint [] cookie)” or “void AckCondition(out uint [] cookie)”. So clarify the prototype of the existing function before calling it.

    Wednesday, November 27, 2013 6:13 AM
  • Hi, Thanks a lot:

    Could you tell me how to change the function prototype to "Void AckCondition(unit[] cookie)", since I don't have the code of "Opc_AE.dll".

    Use The .il file? More detail more better, thanks again.

    Friday, November 29, 2013 2:10 AM
  • If DLL was not designed to work with array, then you cannot send unexpected array data to DLL.

    You need to have the sources in order to make it work with arrays.

    Friday, November 29, 2013 5:44 AM
  • I am sure the dll was designed to work with array,

    I know the function is defined as :

    HRESULT AckCondition(
    [in] DWORD dwCount
    [in, string] LPWSTR szAcknowledgerID,
    [in, string] LPWSTR szComment,
    [in, size_is(dwCount)] LPWSTR* pszSource,
    [in, size_is(dwCount)] LPWSTR* pszConditionName,
    [in, size_is(dwCount)] FILETIME* pftActiveTime,
    [in, size_is(dwCount)] DWORD* pdwCookie,
    [out, size_is(,dwCount)] HRESULT **ppErrors
    );

    after interop convert, the il file shows it is :

    .method public hidebysig newslot abstract virtual
              instance void  AckCondition([in] uint32 dwCount,
                                          [in] string  marshal( lpwstr) szAcknowledgerID,
                                          [in] string  marshal( lpwstr) szComment,
                                          [in] string&  marshal( lpwstr) pszSource,
                                          [in] string&  marshal( lpwstr) pszConditionName,
                                          [in] valuetype ViewPoint.Server.Alarm._FILETIME& pftActiveTime,
                                          [in] uint32& pdwCookie,
                                          [out] native int ppErrors) runtime managed internalcall
      {
      } // end of method IOPCEventServer::AckCondition

    And the function is defined as below in VStudio object browser:

    void AckCondition(uint dwCount, string szAcknowledgerID, string szComment, ref string pszSource, ref string pszConditionName, ref ViewPoint.Server.Alarm._FILETIME pftActiveTime, ref uint pdwCookie, System.IntPtr ppErrors)
        Member of ViewPoint.Server.Alarm.IOPCEventServer2

    As we can see all the array parameters are ref type.

    Monday, December 2, 2013 12:56 AM
  • Now I have figure out the solution about this problem, my idea is right, edit the il file.

    General steps are:

    1. Use TlbImp to create the interop DLL file by "OPC_AE.dll"

    2. Use Ildasm to create il file by interop DLL file.

    3. Edit the il file, change the define content of "AckCondition".

    4. Use Ilasm to recreate interop DLL by the new il file.

    Anyway, thanks for all people reply to me ... So happy to fix it... *_*
    • Marked as answer by Razer518 Wednesday, December 4, 2013 12:44 AM
    Wednesday, December 4, 2013 12:43 AM