簡體   English   中英

從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);

我總是得到一個空字符串。

當我嘗試其他任何一個(字節[],字符串,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.

我在這里想念什么? 謝謝

在.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();
}

您可以分配一個緩沖區,然后傳遞給本機函數。

//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轉換。 如果函數不經常調用或不返回大量數據,則此命中可以忽略不計。

參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM