Reputation: 318
I have searched stackoverflow for this problem but didn't find this exact one. In particular, I've found a ton of questions regarding retrieving C++ string references (char**) when the C# side is managing the memory but not the other way around.
The situation is as follows. I have a DLL (written on VC++ 2012) which I wrote myself. It loads and parses data from files and then lets anyone using the DLL access this data (by actual direct memory access for performance reasons) in several ways. Any program in C++ using this DLL has obviously no problems doing that. C# as it seems does...
A bit of context:
The DLL provides exported functions accepting char** (arrays of char*) parameters whose elements are being set to memory locations in the DLL and then further processed by the DLL's user after the call.
An example might look like this (examplatory implementation):
int myFunction(char* dataArray[], int row)
{
for (int i= 0; i < _something; ++i)
{
dataArray[i] = _some_char_ptr
}
}
And this is what the callee's implementation might look like in C++:
char** data = new char*[__num_fields];
myFunction(data, __some_row);
for (int i= 0; i < __something; ++i)
{
cout << data[i] << endl;
}
Special - thus different from all questions I found - about this is that the callee allocates a list of char* which after the call point to memory locations allocated by the DLL itself.
Now, I must say, I'm only using C# because you can get quite simple GUIs in notime. The C# GUI tool I'm working on is for integrity testing data the DLL loads. I'm not profound of C# at all. What I've tried so far wasn't successful at all and I'm aware there might be no solution for this problem due to C# not having any sort of pointer concepts. Similar problems I found in Java while using JNA to load DLLs there which led to me not using Java for such testing purposes anymore.
Now a bit of C# stuff I've tried, incl. context:
public static class DLLTest
{
// delegate object for the function:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int MyFunction_Type(out string[] dataArray, int row);
public static MyFunction_Type MyFunction { get; private set; }
public static void Load()
{
IntPtr dllAddress = DllUtilities.LoadLibrary(@"__dll_path");
IntPtr procAddress = DllUtilities.GetProcAddress(dllAddress, "myFunction");
MyFunction = (MyFunction_Type)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(MyFunction_Type));
}
}
I'm then calling the function like this:
string[] data = new string[__num_fields];
DLLTest.MyFunction(out data, __row)
Code similar to this using things like normal strings, integers, booleans whatsoever work like a charm. Just these string arrays keep bugging me :-)
Note: I can't change the way the DLL works because I wrote this for my boss and he's using it fine in both C++ and Delphi programs. It performs well and we're not about to change anything on the DLL itself as it really is fine the way it is.
Any help or clarification is highly appreciated, thanks a lot, Greetings
Upvotes: 2
Views: 2446
Reputation: 613282
out string[] dataArray
is the wrong translation for the char**
parameter. It should be:
IntPtr[] dataArray
The calling C# code then allocates the array before calling the function. Just as the C++ code does.
IntPtr[] data = new IntPtr[__num_fields];
int retval = DLLTest.MyFunction(data, __row);
You can then access the memory to your hearts content using the Marshal
class to read the unmanaged memory behind the IntPtr
pointers.
The calling convention looks a bit odd. As written, the C++ function is cdecl
. As Hans says, there must also be some mechanism for the DLL to know how long the passed in array is.
Upvotes: 1