如何在 c# 代码中通过引用调用时从 c++ dll 更新数组值?
How to update array values from c++ dll while calling by reference in c# code?
我正在使用c#代码从c ++ dll调用一个函数(名为cbFunction(。我必须将字符串数组(名为strArray(从c#代码作为参数传递给c ++ 'cbFunction'。在 c++ 函数中,我必须更改数组的值。应在 c# 代码中读回新更改的值。
我面临的问题:
- c# 中 strArray 的基址和 c++ dll 中参数中收到的基址是完全不同的。
- 我可以读取 c++ dll 中的字符串数组。但是,我必须在 c++ 函数中修改数组的值。当我在 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 code (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"}。
提前感谢!
首先,C#中的char
与C++中的char
不同。您需要一个 c# 中的sbyte
,它与 c++ 中的char
相同。为方便起见,我们将使用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 );
编辑
对于完成,有一种更简单的方法可以做到这一点(使用平台调用封送数据,封送不同类型的数组(:
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 );
相关文章:
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Python ctypes:不会按预期加载 dll
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL