3

I have a C++ DLL returning an int* to a C# program. The problem is the int* in C# remains null after the assignment.

When I assign the C++ result to an IntPtr, I get a correct non-null value. However any attempt to convert this to an int* results in null.

I've tried:

IntPtr intp = cppFunction ();           // Non-null.

int* pi = (int *) intp;                 // Results in null.

int* pi = (int *) intp.ToPointer ();    // Results in null.


void* vp = intp.ToPointer ();

int* pi = (int *) vp;                   // Results in null, but vp is non-null.

How can I get a non-null int* ?

Thanks! Alan

Helen
  • 87,344
  • 17
  • 243
  • 314
user20493
  • 5,704
  • 7
  • 34
  • 31
  • I used the standard malloc() function from msvcrt.dll as "cppFunction()". It worked okay for me, I could even read/write the allocated memory location. When I assigned a random number to intp (IntPtr intp = (IntPtr)1000;), I got a NullPointerException only when dereferencing. Still, the pointer's value was never null... Can you give me a small, complete program that produces the incorrect results? – Hali Nov 24 '09 at 00:46
  • do you have the option of refactoring the C++ so that you can pass in an IntPtr with the required memory allocated? it would be better that way - or hook up a callback to allocate the memory in C# as per http://stackoverflow.com/questions/9378626/how-can-i-return-a-stringbuilder-or-other-string-buffer-from-a-pinvoke-native-ca – dice Feb 29 '12 at 15:16

1 Answers1

4

You cppFunction declaration should be something like:

void cppFunction(ref int* ptr) {
   ptr = somevalue;
}

That should solve your problem.

You may find this useful also: http://www.pcreview.co.uk/forums/thread-2902012.php

James Black
  • 41,583
  • 10
  • 86
  • 166
  • Thanks James. I tried your method like this: [DllImport("vdrdll.dll", EntryPoint = @"?getLineContentsAsArg@@YAXAAPAH@Z")] public unsafe static extern void getLineContentsAsArg (ref int* lca); DLLEXPORT void getLineContentsAsArg (int*& lca) { lca = calculateLineContents (); } A pointer value is assigned in the DLL, but when it gets back to C#, it's null. I looked at your examples, and only the last one attempts to assign to a pointer variable in C#. Every time I've tried this, the result of the assignement is null. Can you see anything I'm doing wrong? Thanks! – user20493 May 07 '09 at 15:17
  • I will need to look at it more when I finish mowing, but, I realized that recently the way I solved this was that in C# I allocated a buffer, sent the pointer to the unmanaged code, along with an IntPtr to get the length. The problem you are encountering is probably due to the fact you are expecting the C++ function to do the malloc and return the string. In that case you probably need to pass a pointer to the pointer, but I am not certain how you would free that in C# when you are done with it. – James Black May 07 '09 at 20:52
  • If you need the unmanaged code to do the malloc but you want it in the managed address space you could provide a callback of the form `void* callback(int length)` so the unmanaged code could ask the managed code to do the allocation. Newer C# version support unmanaged delegates and would be needed to define the callback. Another option is passing a buffer guaranteed to be large enough: `int cppFunction(ref int* ptr, void* buffer)` where the `int` return value is how many bytes were written to the `buffer` – mhand Aug 30 '21 at 06:49