Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 678
  • Last Modified:

How to marshal array of custom data type using P/Invoke in C++ .Net

Experts,

I am currently trying to call functions from an unmanaged c++ dll using P/Invoke in C++ .Net (2008).  I am completely new to P/Invoke, but have managed to stumble through by using various online references until now.

One particular function of the unmanaged dll is defined as follows:

PUNCH_BUREAU_RESULT_CODE PunchBureauDoAuthorisation(
      char            *pszPrimaryIPAddress,
      unsigned short usiPrimaryIPPort,
      char            *pszSecondaryIPAddress,
      unsigned short usiSecondaryIPPort,
      unsigned short usiResponseTimeoutInMs,
      char     rgcTransactionTimestamp[12],
      char        *pszPAN,
      char            rgcExpiryDate[4],
      char            *pszStationID,
        __int64        i64Amount,
        unsigned short usiBatch,
      unsigned short usiCurrencyCode,
      unsigned short usiNumberOfProducts,
      PRODUCT_DATA_DSCR rgProductData[18],
      char rgcActionCode[3],
      char rgcApprovalCode[6]);

PRODUCT_DATA_DSCR is a struct defined in the library.

I currently have the following for the P/Invoke:

[DllImport("PunchBureauInterfaceDLL80.dll",
EntryPoint="?PunchBureauDoAuthorisation@@YA?AW4PUNCH_BUREAU_RESULT_CODE@@PADG0GGQAD010_JGGGQAUPRODUCT_DATA_DSCR@@11@Z",
CallingConvention=CallingConvention::StdCall)]
static PUNCH_BUREAU_RESULT_CODE PunchBureauDoAuthorisation(
      String^ pszPrimaryIPAddress,
      System::UInt16 usiPrimaryIPPort,
      String^      pszSecondaryIPAddress,
      System::UInt16 usiSecondaryIPPort,
      System::UInt16 usiResponseTimeoutInMs,
      String^     rgcTransactionTimestamp,
      String^            pszPAN,
      String^            rgcExpiryDate,
      String^            pszStationID,
      System::Int64       i64Amount,
      System::UInt16 usiBatch,
      System::UInt16 usiCurrencyCode,
      System::UInt16 usiNumberOfProducts,
      ???PRODUCT_DATA_DSCR rgProductData[18]???,
      String^ rgcActionCode,
      String^ rgcApprovalCode);

The questionsI have currently are:

- What is the syntax for marshalling the arguments of the function?  I presume I have to marshall the char arrays to Strings, but if I try the follwing syntax:

...
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 12)]
String^     rgcTransactionTimestamp,
...

I get the compiliation error 'API call 'DefineCustomeAttribute" failed.

- How can I successfully marshal an array of a custom datatype?

I think I have been thrown in the deep end of P/Invoke!  Many thanks for your help in advance.

Alvin
0
batbertram
Asked:
batbertram
1 Solution
 
magicdlfCommented:
Please read this article:
http://www.codeproject.com/KB/cs/marshalarrayofstrings.aspx
For my own experience, don't use attribute to do this work, you will be crazy and end up with no good solution with this. Using the IntPtr to handle all the pointers and you can parse any data yourself.
0
 
batbertramAuthor Commented:
Thanks for the link magicdlf.  

I have tried adapting the solution but have yet to achieve the desired result.  I don't think I have the expertise required!

We are going to opt for a slight recode of the C++ libraries where it is only accepting simple datatypes, with a delimited string passed instead of the array.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now