问题
As the title suggests I would like to let a string array be described in a function which is in a C++ DLL.
In my actual attempt it runs without exception, but my strArray
does not contain any objects after the C++ Function call.
My C# Code:
var strArray = new StringBuilder[100];
for (int i = 0; i < strArray .Length; i++)
{
strArray[i] = new StringBuilder(50);
}
modifyStringInCpp(strArray);
[DllImport(DllFilePath, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private extern static void modifyStringInCpp(StringBuilder[] strA);
My C++ Code:
extern "C" {
__declspec(dllexport) void __cdecl modifyStringInCpp(char** strA)
{
for (size_t i = 0; i < 100; i++)
{
strcpy(strA[i], "testString");
}
}
}
What do I need to change?
回答1:
Sadly there is no default marshaling for StringBuilder[]
... It then becomes a PAIN... A PAIN!!!
You have to do everything manually! :-(
[DllImport("CPlusPlusSide.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private extern static void modifyStringInCpp(IntPtr[] strA);
and then:
var strArray = new byte[100][];
for (int i = 0; i < strArray.Length; i++)
{
// 49 characters + NUL
strArray[i] = new byte[50]; // or a size you choose
}
var handles = new GCHandle[strArray.Length];
string[] strings;
try
{
var ptrs = new IntPtr[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
handles[i] = GCHandle.Alloc(strArray[i], GCHandleType.Pinned);
ptrs[i] = handles[i].AddrOfPinnedObject();
}
modifyStringInCpp(ptrs);
strings = new string[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
strings[i] = Marshal.PtrToStringAnsi(ptrs[i]);
}
}
finally
{
for (int i = 0; i < strArray.Length; i++)
{
if (handles[i].IsAllocated)
{
handles[i].Free();
}
}
}
来源:https://stackoverflow.com/questions/42928094/passing-c-sharp-string-array-to-c-dll-and-modify-it-there