views:

88

answers:

2

I have a function definition in my VC++ Win32 DLL

DEMO2_API void ProcessData(char* i_buff, unsigned short i_len, char* o_buf,
unsigned *o_len, unsigned short *errorCode)
{
    __describe (i_buff,&i_len,o_buf,o_len,errorCode);
}

This dll function is called by a c# application. When called, it generate access violation exception.

After reasearching i found, the cause for my problem.

http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/6e843243-baf4-4eb1-8a20-c691ad47762c

But could not understand what exactly they are doinng in example code. Can someone explain it so me?

And what would be P/Invoke signature in c# after externally allocating memory?

A: 

C# uses IntPtr to represent externally allocated memory. C# pointers and references can only be used with memory provided by the garbage collector.

The System.InteropServices.Marshal class provides some methods for interacting with native memory areas represented by IntPtr, of course they aren't typesafe.

But I don't see anything in your function that could return a pointer to allocated memory. You'd need a double-pointer argument, or a pointer return value, and you have neither.

EDIT to add example as requested:

// this doesn't work right
void external_alloc_and_fill(int n, int* result)
{
  result = new int[n];
  while (n-- > 0) { result[n] = n; }
}

extern external_alloc_and_fill(int n, int* result)
int a = 5;
fixed (int* p = &a) {
  external_alloc_and_fill(17, p);
  // p still points to a, a is still 5
}

better:

// works fine
void external_alloc_and_fill2(int n, int** presult)
{
  int* result = *presult = new int[n];
  while (n-- > 0) { result[n] = n; }
}

extern external_alloc_and_fill2(int n, ref IntPtr result)
int a 5;
IntPtr p = &a;
external_alloc_and_fill2(17, ref p);
// a is still 5 but p is now pointing to the memory created by 'new'
// you'll have to use Marshal.Copy to read it though
Ben Voigt
@Ben Voigt Third parameter *o_buf would be return to my application. and i need it as byte array
Manjoor
@Manjoor: Either the caller allocates the space and passes a pointer to it, or the callee allocates the space and needs to store the pointer somewhere, i.e. a pointer-to-pointer. There's no way a pointer passed by value (like your o_buf is) can be used to return a buffer allocated inside the callee.
Ben Voigt
hmmmm. Can you show me by a 4 line example?
Manjoor
this example is four lines for each of the C++ and C# part, is that ok?
Ben Voigt
Thanks for the nice solution. The problem seems to be somewhere else. I could not solve it till now. I have added another question with full source. check http://stackoverflow.com/questions/2415492/using-lzo-library-in-c-application
Manjoor
A: 

I changed passing mode of O_len to out instead of ref and it works.

Thnaks everyone for giving nice answers and comments. I hope this would be useful for other community members ( plus those googling...)

Manjoor