Click to See Complete Forum and Search --> : [RESOLVED] Passing pointers as a source and destination into a DLL call
ifdef
November 3rd, 2008, 09:53 AM
I’m trying to access a function in a DLL from C# that I compiled in C++ with the signature:
bool DecodeJpeg(byte* arrayPointer, int arrayLength, byte* &newArray)
How would I go about passing the information from C# if I want to pass a simple array pointer and then use newArray as the data I want returned from the function?
From what I have been reading I will be trying this:
bool DecodeFile(byte* arrayPointer, int arrayLength, byte* &newArray)
Byte[] someArray;
Byte* rp;
//open a file, and assign enough memory to the array to hold the file
int len = someArray.length();
fixed(byte* bp = someArray)
{
DecodeFile(bp, len, rp)
}
I’m concerned with the way the array will be passed to the DLL and how the memory that will be allocated in the DLL will be handled when it is passed back into my C# code. Will just a pointer be adequate to access the data? How will it be affected by garbage collection?
Because of my use of a reference and a pointer in the C++ code I think I should use the out statement in the signature in C#. Is this correct? E.g.:
public static extern bool DecodeFile(byte* data, int len, out byte* fileMap);
Thanks for any information you have.
ifdef
November 3rd, 2008, 12:31 PM
I was able to get this to work using the following Signature:
bool DecodeFile(byte* data, int len, out byte* fileMap);
and calling it like
fixed (byte* bp = byteArray)
{
DecodeFile(jp, byteArray.Length, out returnPointer);
}
I would still like to know how the memory created in the DLL is managed and more about "out" if any one know about it.
BigEd781
November 3rd, 2008, 02:03 PM
The memory in the DLL is not managed, and the out keyword in C# means that the variable is passed by address and will be assigned a value inside the routine. Also, using the out keyword means that the variable that is passed does not have to be initialized beforehand (but must be assigned a value inside the function). I don't think that would work if you were calling into a C++ dll. Perhaps I am wrong about that...
ifdef
November 3rd, 2008, 02:17 PM
if what you are say about the memory allocation coming from in side the .dll and the garbage collector not tracking memory being pointed to with my pointer. How can I clean up the memory that the DLL is creating?
BigEd781
November 3rd, 2008, 02:40 PM
If you are passing a pointer, you must be using the unsafe context anyway, so you would clean up anything that you allocated. Your DLL is responsible for cleaning up after itself. There are people around here who know more about interop than I do, they could give you some more insight.
darwen
November 4th, 2008, 02:51 AM
BigEd is quite right. You can't destroy memory allocated in the dll outside the dll in C#. The dll should have a 'destroy' method or the like which C# passes the pointer into to be destroyed.
Darwen.
ifdef
November 5th, 2008, 04:14 PM
I wrote a function in the DLL to destroy the memory at a pointer. I originally assign the memory to the pointer with malloc() so in the function to destroy the memory I am using free(). However when i try to run the code i get a error about trying to access protected memory.
Here are the function call and prototype in C# and the function in C++
//C#
unsafeFunks.destroyData(out dataPointer);
[DllImport("MrDll.dll")]
public static extern bool destroyData(out byte* data);
//C++
__declspec(dllexport) bool destroyData(byte* data)
{
if (data != 0x00)
{
free(data);
data = 0x00;
return true;
}
else
return false;
}
In the past i have used New and Delete and know about their connection to the constructor/destructor calls. How dose free() know what to free if in C++ pointers just point to a number of a memory address and arrays don't have any information about their length?
Should i walk the array with Free to make sure it is removing the whole thing?
If the pointer has not changed since its original assignment in the DLL why dose it though a protected memory error?
Thanks for the information!!
darwen
November 5th, 2008, 04:56 PM
You should use
[DllImport("MrDll.dll")]
public static extern bool destroyData(byte* data);
No 'out'.
memory address and arrays don't have any information about their length?
When you allocate memory using malloc the native memory manager remembers how much memory was initially allocated at this address so when you call free on the same address it knows how much to deallocate.
For every call to malloc you should have a call to free.
However you can do all of this by using 'new' e.g.
// C++ example
void AllocateMemory(char *&data)
{
data = new char[100];
}
void DeallocateMemory(char *data) // no & because we're not returning anything
{
delete [] data; // scalar deleting destructor
}
By using the form delete[] you're telling the delete operator that what was created was an array, so it'll go off and get the size of the array initially allocated.
It doesn't matter how it remembers this : it just does.
However what is considerably better is to take the approach that dlls never allocate memory themselves : they tell the client code how much memory they need and then just fill it in e.g.
// C++
void AllocateMemory(byte *data, int &amount)
{
if (data == 0)
{
amount = 10;
}
else
{
strcpy(data, "hello you");
}
}
// C#
class Example
{
[DllImport("MyDll.dll")]
static private unsafe extern void AllocateMemory(byte *data, ref int amount);
static public unsafe byte [] GetData()
{
int amount = 0;
AllocateMemory(null, ref amount);
byte [] data = new byte[amount];
fixed (byte *pData = &(data[0]))
{
AllocateMemory(pData, ref amount);
}
return data;
}
}
You don't have to worry about deallocation of memory in this case : the memory allocated is managed so will be taken care of by the GC.
Darwen.
ifdef
November 5th, 2008, 05:06 PM
Thanks for the explination. With new/delete dose it matter if the reference has passed from the dll to my C# code back to the dll?
Originally the pointer is created in C# then passed to the DLL where it is assigned memory. Later when I am done with it I pass the pointer back to be cleaned up. Will free still remember how much memory to clean up?
darwen
November 5th, 2008, 05:09 PM
Yes, because the pointer which is passed back is just a number.
Also, see my edits above about allocating memory outside the dll which the dll then fills with information. This is far, far preferable to allocating the memory inside the dll because you don't have to worry about cleaning it up afterwards.
Darwen.
ifdef
November 6th, 2008, 02:56 PM
Darwin,
I looked at the update to the code and moved the memory allocation into C# and not only dose the code works now but runs faster.
It turns out once i was able to get the potential memory footprint before running the main call to the dll I was able to get rid of some other code that was essentially doing the same thing.
Thanks for all the information.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.