|
-
November 3rd, 2008, 10:53 AM
#1
[RESOLVED] Passing pointers as a source and destination into a DLL call
I’m trying to access a function in a DLL from C# that I compiled in C++ with the signature:
Code:
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:
Code:
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.:
Code:
public static extern bool DecodeFile(byte* data, int len, out byte* fileMap);
Thanks for any information you have.
-
November 3rd, 2008, 01:31 PM
#2
Re: Passing pointers as a source and destination into a DLL call
I was able to get this to work using the following Signature:
Code:
bool DecodeFile(byte* data, int len, out byte* fileMap);
and calling it like
Code:
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.
-
November 3rd, 2008, 03:03 PM
#3
Re: Passing pointers as a source and destination into a DLL call
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...
-
November 3rd, 2008, 03:17 PM
#4
Re: Passing pointers as a source and destination into a DLL call
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?
-
November 3rd, 2008, 03:40 PM
#5
Re: Passing pointers as a source and destination into a DLL call
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.
Last edited by BigEd781; November 3rd, 2008 at 03:43 PM.
-
November 4th, 2008, 03:51 AM
#6
Re: Passing pointers as a source and destination into a DLL call
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.
-
November 5th, 2008, 05:14 PM
#7
Re: Passing pointers as a source and destination into a DLL call
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++
Code:
//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!!
-
November 5th, 2008, 05:56 PM
#8
Re: Passing pointers as a source and destination into a DLL call
You should use
Code:
[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.
Code:
// 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.
Code:
// 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.
Last edited by darwen; November 5th, 2008 at 06:05 PM.
-
November 5th, 2008, 06:06 PM
#9
Re: Passing pointers as a source and destination into a DLL call
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?
-
November 5th, 2008, 06:09 PM
#10
Re: Passing pointers as a source and destination into a DLL call
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.
-
November 6th, 2008, 03:56 PM
#11
Re: Passing pointers as a source and destination into a DLL call
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|