[英]How to update array values from c++ dll while calling by reference in c# code?
我正在使用c#代码从c ++ dll调用一个函数(名为cbFunction)。 我必须从c#代码传递字符串数组(名为strArray),作为c ++'cbFunction'的参数。 在c ++函数内部,我必须更改数组的值。 新更改的值应以c#代码读回。
我面临的问题:
C#代码
public static class Call_API
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool CallBackFunction(string[] argv, int argc);
private static string[] strArray;
public static void ChangeValue()
{
IntPtr pDll = NativeMethods.LoadLibrary("DllFunctions.dll");
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "cbFunction");
string args = "Hello Disney World";
strArray = args.Split(' ');
CallBackFunction cbFunction = ((CallBackFunction)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall, typeof(CallBackFunction));
if(false == cbFunction(strArray, strArray.Count()))
{
//some task
}
}
}
C ++ dll代码(DllFunctions.dll):
bool cbFunction(char** argv, int argc)
{
//Some task
char VarValue[256] = { 0 };
std::string s = "Jetix";
sprintf_s(VarValue, s.c_str());
strcpy_s(argv[1], sizeof(VarValue), VarValue);
return false;
}
根据此代码,我在strArray(在c#中)末尾的期望值为{“ Hello”,“ Jetix”,“ World”}。
提前致谢!
首先一个的char
在C#中是不一样的char
在C ++中。 您需要一个sbyte
在C#这是相同的char
在C ++中。 为了方便起见,我们将使用一个byte
。 工作正常。
码:
string args = "Hello Disney World";
string[] strArray = args.Split( ' ' );
byte[][] byteArray = new byte[ strArray.Length ][ ];
//convert string to byte array
for( int i = 0; i < strArray.Length; i++ ) {
byteArray[ i ] = Encoding.ASCII.GetBytes( strArray[ i ] );
}
要获得一个byte**
,您需要一个byte*[]
(更多信息,在C#中从锯齿状数组转换为双指针 ):
unsafe
{
GCHandle[] pinnedArray = new GCHandle[ byteArray.Length ];
byte*[] ptrArray = new byte*[ byteArray.Length ];
for( int i = 0; i < byteArray.Length; i++ ) {
pinnedArray[ i ] = GCHandle.Alloc( byteArray[ i ], GCHandleType.Pinned );
}
for( int i = 0; i < byteArray.Length; i++ ) {
ptrArray[ i ] = (byte *)pinnedArray[ i ].AddrOfPinnedObject();
}
fixed ( byte **ptr = &ptrArray[ 0 ] ) {
IntPtr mptr = (IntPtr)ptr;
if( false == cbFunction( mptr, strArray.Count() ) ) {
//some task
}
}
for( int i = 0; i < pinnedArray.Length; i++ )
pinnedArray[ i ].Free();
}
您的声明应为:
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool CallBackFunction( IntPtr argv, int argc );
编辑
为了完成,有一种更简单的方法( 使用Platform Invoke整理数据 , 整理不同类型的数组 ):
bool cbFunction(char *argv[], int argc)
{
//Some task
STRSAFE_LPSTR temp;
const size_t alloc_size = sizeof(char) * 5; //"Jetix" num of characters
temp = (STRSAFE_LPSTR)CoTaskMemAlloc( alloc_size );
StringCchCopyA( temp, alloc_size, (STRSAFE_LPSTR)"Jetix" );
CoTaskMemFree( argv[1] );
argv[1] = (char *) temp;
return false;
}
称它为:
string args = "Hello Disney World";
strArray = args.Split(' ');
CallBackFunction cbFunction = ((CallBackFunction)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall, typeof(CallBackFunction));
if( false == cbFunction(strArray, strArray.Count()) )
{
//some task
}
并声明:
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
public delegate bool CallBackFunction( [In, Out] String[] argv, int argc );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.