2013-05-08 194 views
1

我正在嘗試將C++ DLL集成到我們的C#應用​​程序中,但我無法確定調用其方法之一的正確方法。在文件的兩個不同地方的方法定義不相等:從C#應用程序調用C++ DLL

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. 

缺少什麼我在這裏? 謝謝

回答

0

您可以分配一個緩衝區,然後傳遞到本地功能。

//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轉換。如果該函數沒有被頻繁調用或者不返回大量數據,則該命中可能可以忽略不計。

參考:

0

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