Reputation: 161
i am having trouble importing c++ unmanaged dll into C# [winform]. Can someone help?
Basically i am just trying to create a safearray of strings in c++ and trying to send it to C#.
Here is my c++ code.
extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY* arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound);
VARIANT* pvData = (VARIANT*)(myArray->pvData);
pvData[0].vt = VT_BSTR;
pvData[0].bstrVal = SysAllocString(L"FirstString");
pvData[1].vt = VT_BSTR;
pvData[1].bstrVal = SysAllocString(L"SecondString");
pvData[2].vt = VT_BSTR;
pvData[2].bstrVal = SysAllocString(L"ThirdString");
pvData[3].vt = VT_BSTR;
pvData[3].bstrVal = SysAllocString(L"FourthString");
pvData[4].vt = VT_BSTR;
pvData[4].bstrVal = SysAllocString(L"FifthString");
arr = myArray;
return true;
}
Here is my c# code.
[DllImport("MyData.dll", EntryPoint = "GetStringArr")]
public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out Array strServerList);
i am getting exception when i call GetStringArr from C#. i am sure there is something silly i am doing. Can someone please help?
Thanks in advance.
Upvotes: 0
Views: 2231
Reputation: 53709
Some problems on both the C and .NET side of things
On the C side
C Code
extern "C" __declspec(dllexport)
BOOL GetStringArr(SAFEARRAY** arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound);
BSTR* pvData = (BSTR*)(myArray->pvData);
pvData[0] = SysAllocString(L"FirstString");
pvData[1] = SysAllocString(L"SecondString");
pvData[2] = SysAllocString(L"ThirdString");
pvData[3] = SysAllocString(L"FourthString");
pvData[4] = SysAllocString(L"FifthString");
*arr = myArray;
return true;
}
On the .NET side
out string[]
to get the pointer to the SAFEARRAY.NET Code
class Program
{
static void Main(string[] args)
{
string[] data;
bool b = GetStringArr(out data);
}
[DllImport("MyData.dll",
CallingConvention = CallingConvention.Cdecl)]
public static extern bool GetStringArr(
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)]
out string[] strServerList);
}
Upvotes: 1
Reputation: 942119
Several problems in your C++ code. You are returning an array, that requires the argument to be SAFEARRAY**. You also are stuffing the array with the wrong data, you created an array of strings but you are writing VARIANTs. Not sure what the intention was, I'll keep variants in the code fix:
extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY** arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
VARIANT* pvData = 0;
SafeArrayAccessData(myArray, (void**)&pvData);
pvData[0].vt = VT_BSTR;
pvData[0].bstrVal = SysAllocString(L"FirstString");
// etc..
SafeArrayUnaccessData(myArray);
*arr = myArray;
return true;
}
C# code:
object[] array;
bool ok = GetStringArr(out array);
[DllImport(@"blah.dll", EntryPoint = "GetStringArr")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out object[] strServerList);
Upvotes: 1
Reputation: 9244
I recommend you add a C++/CLI project (assembly) to your C# solution. That will enable you to write code that live in both managed and unmanaged land simultaneously. That means that your C++/CLI code can create a List<string^>
instead and add managed strings to it before you return it to C#. :-)
Upvotes: 0
Reputation: 54178
Do you have access to the native DLL's source? If so you can enable unmanaged debugging in your Managed projects options, and step thru the unmanaged code (preferably Debug build) to see what's going on. If nothing else you can enable Exceptions in the debugger options, and debug to see where the native exception gets thrown.
Upvotes: 0