你能帮我解决一下这个问题吗?我有一个C ++函数dll,它将由另一个C#应用程序调用。我需要的功能之一如下:
unsigned long makeArray(unsigned char* sendArr, unsigned long sendArrLen, unsigned char *recvArr, unsigned long *recvArrLen);
我在C#中编写了以下代码:
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong makeArray(byte[] sendArr, ulong sendArrLen, byte[] recvArr, ulong recvArrLen);
private byte[] MakeArray()
{
byte[] arrSend = new byte[] { 0x00, 0x12, 0x34 };
ulong nRecvArrLen = 0;
byte[] arrRecv = null; // assign in c++ dll function (variable size)
if(makeArray(arrSend, (ulong)arrSend.Length, arrRecv, nRecvArrLen) == 1)
{
return arrRecv;
}
return null;
}
不幸的是,上面的代码不起作用...... 我可以知道如何将指针传递给C ++函数?如果不可能,有任何解决方法吗?
谢谢。
答案 0 :(得分:1)
unsigned long
是一个32位无符号整数,因此您应该将其映射到System.UInt32
.NET类型,对应于C#中的uint
关键字。
C#ulong
是无符号的64位整数,对应于MSVC的unsigned __int64
或unsigned long long
。
我应该在C#PInvoke声明中使用unsigned long *recvArrLen
映射ref
参数,因为你有通过指针的间接级别。
似乎arrRecv
数组参数应由调用者分配(在您的情况下为C#),并由DLL函数填充。
如果DLL函数分配缓冲区,则应添加另一级别的间接(unsigned char **recvArr
),并且应提供释放已分配内存的方法(例如,DLL也应导出释放函数)。
我会尝试使用PInvoke这样的东西:
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint makeArray(
byte[] sendArr,
uint sendArrLen,
[Out] byte[] recvArr,
ref uint recvArrLen
);
答案 1 :(得分:0)
你的'test.dll'在哪里?我认为这是一个路径问题...
该文件必须位于以下目录之一..
[%SystemRoot%] (Windows directory)
[%SystemRoot%]\system32\(32 bit) or
[%SystemRoot%]\sysWOW64\(64 bit)
The same location with your executable file
PATH variable
或者它可能是类型不匹配...请参阅 [site]。
我在桌面上的c / c ++中将ulong类型的csharp与unsigned __int64匹配。
C#代码的声明稍有改动。
[DllImport(@"testdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern ulong makeArray
(
byte[] sendArr,
ulong sendArrLen,
[Out] byte[] recvArr,
ref ulong recvArrLen
);
以下是我测试的testdll.cpp abd testdll.h
#include "testdll.h"
unsigned __int64 makeArray(
unsigned char* sendArr,
unsigned __int64 sendArrLen,
unsigned char *recvArr,
unsigned __int64 *recvArrLen
)
{
int i;
for(i=0; i < sendArrLen; i++)
{
recvArr[i] = sendArr[i];
}
memcpy(recvArrLen, &sendArrLen, sizeof(unsigned __int64));
return i;
}
testdll.h代码。
#pragma once
#ifdef EXPORT_TESTDLL
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C" TESTDLL_API unsigned __int64 makeArray(
unsigned char* sendArr,
unsigned __int64 sendArrLen,
unsigned char *recvArr,
unsigned __int64 *recvArrLen
);
最后,控制台应用程序的C#代码如下,在c ++中调用本机dll函数 - testdll.dll 在控制台上打印项目。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
[DllImport(@"testdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern ulong makeArray(byte[] sendArr, ulong sendArrLen, [Out] byte[] recvArr, ref ulong recvArrLen);
static byte[] MakeArray()
{
byte[] arrSend = new byte[] { 0x00, 0x12, 0x34 };
ulong nRecvArrLen = 0;
ulong ret = 0;
byte[] arrRecv = new byte[3]; // assign in c++ dll function (variable size)
try
{
if ((ret = makeArray(arrSend, (ulong)arrSend.Length, arrRecv, ref nRecvArrLen)) > 0)
{
if(arrRecv != null)
Console.WriteLine("nRecvArrLen2============>" + arrRecv.Length);
return arrRecv;
}
}
catch (DllNotFoundException dne)
{
Console.WriteLine("============> dll not found....");
}
return null;
}
static void Main(string[] args)
{
byte[] retbytes = MakeArray();
if (retbytes != null)
{
Console.WriteLine("=====LEN=======>" + retbytes.Length);
for (int i = 0; i < retbytes.Length; i++)
Console.WriteLine("====ITEM========>" + retbytes[i]);
}
else
Console.WriteLine("=====NULL=======>");
}
}
}