c# - 从 C# 应用程序调用 C++ DLL

标签 c# c++ .net dll interop

我目前正在尝试将 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.

我在这里错过了什么? 谢谢

最佳答案

您可以分配一个缓冲区,然后传递给 native 函数。

//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 的默认编码(marshal)拆收器:

[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 转换创建一个编码缓冲区。如果函数不被频繁调用或不返回大量数据,则此命中可以忽略不计。

引用:

关于c# - 从 C# 应用程序调用 C++ DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16446156/

相关文章:

C# 有没有办法创建接受匿名函数代码作为参数的函数?

c# - 有没有办法像 python 一样在 C# 中制作类方法?

c# - 在 WCF 客户端应用程序之间共享静态 dll

android - QT 快速获取最后已知位置

c++ - opencl中分配的缓冲区在哪里?

c# - 在 C# 中,搜索列表中的元素但执行 "StartsWith()"搜索的最快方法是什么?

c# - NHibernate:从多对多关系中删除 child 会导致异常

c++ - (linux)Socket 返回 0

c# - 检查类型 TA 是否可以在运行时转换为类型 TB? (考虑的不仅仅是继承)

.net - 您将如何创建数据继承数据库?