从c#应用程序调用c++ DLL
Call a C++ DLL from a C# application
我目前正在尝试将c++ DLL集成到我们的c#应用程序中,但我无法确定调用其中一个方法的正确方式。在文档的两个不同地方,方法定义是不相等的:
ImageAndScanError GetMicrInfo(unsigned char *ptrCodeline,int* iLength)
ImageAndScanError WINAPI GetMicrInfo(char* cMicrInfo,int* iInfoLength);
/*
ImageAndScanError GetMicrInfo(unsigned char *ptrCodeline,int* iLength)
Parameters:
ptrCodeline: a pointer to the output buffer that will receive the code line read by the MICR algorithm. The ptrCodeline should allocate room for 96 characters.
iLength: the number of characters contained in the code line
Function: Read MICR line on the check. This function must be called after StartScan .
Returns: ErrorNone is returned upon success. Otherwise, an enum ImageAndScanError value that indicates the reason for failure is returned.
*/
这就是我如何包含dll方法
[DllImport("ScanDll.dll", CallingConvention = CallingConvention.Winapi)]
这是目前为止我做过的所有组合
public static extern ImageAndScanError GetMicrInfo(out IntPtr cMicrInfo, out int iInfoLength);
public static extern ImageAndScanError GetMicrInfo(out byte[] cMicrInfo, out int iInfoLength);
public static extern ImageAndScanError GetMicrInfo(out string cMicrInfo, out int iInfoLength);
public static extern ImageAndScanError GetMicrInfo(out StringBuilder cMicrInfo, out int iInfoLength);
IntPtr cMicrInfoTMP;
byte[] cMicrInfoTMP= new byte[96];
string cMicrInfoTMP;
StringBuilder cMicrInfoTMP;
GetMicrInfo(out cMicrInfoTMP, out iInfoLengthTMP);
当我使用IntPtr时,在VS2010中调试给我的值是859256727,大小为4,当我执行
时string myString = Marshal.PtrToStringAnsi(cMicrInfoTMP);
我总是得到一个空字符串
当我尝试任何其他(byte[], string, StringBuilder)时,我得到
The runtime has encountered a fatal error. The address of the error was at
0x53e6716a, on thread 0x1084. The error code is 0xc0000005. This error may
be a bug in the CLR or in the unsafe or non-verifiable portions of user
code. Common sources of this bug include user marshaling errors for COM-interop
or PInvoke, which may corrupt the stack.
我在这里错过了什么?由于
您可以分配一个缓冲区,然后传递给本机函数。
//error handling omitted
[DllImport("your.dll", CharSet = CharSet.Ansi)]
ImageAndScanError GetMicrInfo(IntPtr ptrCodeline,ref int bytesCopied);
IntPtr ip = Marshal.AllocCoTaskMem(bufferLen);
Win32API.ZeroMemory(ip, (uint)(bufferLen));
int bytesCopied=0;
GetMicrInfo(ip, ref bytesCopied);
string info= Marshal.PtrToStringAnsi(bytesCopied);
Marshal.FreeCoTaskMem(ip);
如果您不需要在多次调用GetMicrInfo期间重用缓冲区,您可以使用StringBuilder的默认封送器:
[DllImport("your.dll", CharSet = CharSet.Ansi)]
ImageAndScanError GetMicrInfo(StringBuilder ptrCodeline,ref int bytesCopied);
StringBuilder ptrCodeline(bufferLen);
int bytesCopied=0;
GetMicrInfo(ptrCodeline, ref bytesCopied);
如果多次调用GetMicrInfo,它会带来性能损失,因为在每次调用时,默认的CLR编组器都会创建一个用于固定和unicode-ANSI转换的编组缓冲区。如果函数不经常被调用或不返回大量数据,则此命中可以忽略不计。
参考:- 字符串默认封送处理
- 托管和非托管代码之间的封送处理
在。net中,当被调用者创建对象时使用out
参数。您需要为函数提供一个现有的缓冲区,因此应该首先初始化StringBuilder。然后,编组程序将指向对象的内部字符缓冲区的指针传递给函数。
您必须弄清楚MICR字符串使用的是哪个字符集和编码。它可以是UTF-16,在这种情况下,将声明更改为CharSet.Unicode
。
试试这个:
[DllImport("ScanDll.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi)]
private static extern ImageAndScanError GetMicrInfo(StringBuilder cMicrInfo, out int iInfoLength);
public String GetMicrInfo()
{
StringBuilder info = new StringBuilder(96);
int length;
ImageAndScanError error = GetMicrInfo(info, out length);
if (error != ImageAndScanError.ErrorNone) throw new Exception(String.Format("GetMicrInfo error: {0}", error));
return info.ToString();
}
相关文章:
- 挂起和取消挂起一个文件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