C#编组(C#调用C++ DLL)
请问你们能帮我解决下面的问题吗?我有一个C++函数DLL,它将被另一个C#应用程序调用。其中一个我需要的功能是如下:C#编组(C#调用C++ DLL)
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++ func的指针?如果这是不可能的,是否有任何解决方法?
谢谢。
你的'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++在Windows上将ulsha类型的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#代码,调用本地DLL函数在C++中 - 在控制台上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=======>");
}
}
}
在MSVC unsigned long
是一个32位无符号整数,因此应该将其映射到System.UInt32
.NET类型中,对应于C#中的uint
关键字。
C#ulong
是一个无符号的64位整数,对应于MSVC的unsigned __int64
或unsigned long long
。
在C#PInvoke声明中,我应该使用ref
映射unsigned long *recvArrLen
参数,因为您通过指针具有间接级别。
似乎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
);
错误是 “System.AccessViolationException”。而不是“EntryPointNotFoundException”。 –
你的标题中是否有extern关键字?像extern“C”__declspec(dllexport) – tommybee