views:

217

answers:

4

I have an unmanaged C++ dll that exports the following methods:

ERASURE_API  void encode(unsigned char ** inp, unsigned char ** outp,
     unsigned int *block_nums, size_t num_block_nums, size_t sz);

ERASURE_API void decode(unsigned char ** inp, unsigned char ** outp,
     unsigned int * index, size_t sz);

Size of inp and outp can be as large as 10KB, What would be the best performance way to call these methods from C# managed code?

EDIT: I did the following implementation, and It works, but is it the most efficient way to do this.

C++ :

ERASURE_API  void encode_w(unsigned char * inpbuf,int k, unsigned char * outpbuf,
    int nfecs, unsigned int * block_nums, size_t num_block_nums, size_t sz)
{ 
   unsigned char ** inp= new unsigned char*[k];
 for(i=0;i<k;i++){
  inp[i] = inpbuf+i*sz;
 }

unsigned char ** outp= new unsigned char *[nfecs];
 for(i=0;i<nfecs;i++){
  outp[i] =outpbuf+i*sz;
 }
    encode(inp,outp,block_nums,num_block_nums,sz);
    delete [] inp;
    delete [] outp;
}

C#:

[DllImport("erasure.dll")]
public static extern void encode_w([In] byte[] inpbuf,int k,[Out] byte[] outpbuf,
     int nfecs, uint[] block_nums, int num_block_nums, int sz);
+2  A: 

Is C++/CLI an option? IMO, it's these sorts of complex interop/custom marshaling scenarios for which it was designed.

Brannon
How much performance drawback we are talking here with C++/CLI. I need a fast implementation for erasure encoding and decoding, that's why I preferred to choose C++ unmanaged.
rkatiyar
Sorry, I meant: use C++/CLI for the interop between native/managed. The downside is: you end up with 3 codebases (1 native C++, 1 C++/CLI, 1 C#).
Brannon
Of course, if you own the native C++ library, you can tailor the interface to better support P/Invoke. If that is the case, describe your scenario a little more so someone can give a P/Invoke-friendly recommendation.
Brannon
I added code that I did for this problem, I hope the scenario is more clear now.
rkatiyar
A: 

I would recommend creating COM wrapper for these functions.

Alex
I believe that is what he's trying to do. The problem is marshalling the char ** back to C#.
ParmesanCodice
He can represent char** as a separate interface and provide convenient methods for accessing data
Alex
I mean to create COM wrapper in C++, not C#. And than use it in C#
Alex
@Alex, now I see what you are saying. I've had to do that before, in VB 6.0. I thought those days were over :)
ParmesanCodice
+1  A: 

Errg that's some awesome Marshalling to be done there.

I've only ever come across one good article that deals with this sort of thing:
Marshalling a Variable-Length Array From Unmanaged Code In C#

ParmesanCodice
+1  A: 

Do you have to marshal data between managed and native heap? If you move all operation on the buffer to your native DLL you can avoid the cost of data copy between heaps.

That means you need to allocate the data on the native heap, return it in a ref IntPtr parameter, then hold the buffer's address in IntPtr (.Net equivalent of void*) and pass it around. After you are done with the buffer you can call another function in your native dll to delete the buffer. Use System.Runtime.InteropServices.Marshal.Copy when you have to copy the data to the managed heap (that's what the CLR marshaller called for marshalling built-in types).

Creating COM wrappers of the buffer-operating functions would be a little slower but makes the code more readable. However, allocating on the COM heap could be a little slower because managed code can also locking the COM heap.

Sheng Jiang 蒋晟
Thanks for your comment,I will definitely try out your suggestions. I am very new to .NET and c#. I didn't know IntPtr were equivalent to void*. I thought they would only hold int refs :(
rkatiyar