1

現在、C++ DLL を C# アプリケーションに統合しようとしていますが、メソッドの 1 つを呼び出す正しい方法を特定できません。ドキュメントの 2 つの異なる場所で、メソッド定義が等しくありません。

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 でデバッグによって得られる値は、サイズが 4 の 859256727 です。

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.

ここで何が欠けていますか?ありがとう

4

2 に答える 2

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();
}
于 2013-05-08T17:56:09.827 に答える
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 変換用のマーシャリング バッファーを作成するためです。関数が頻繁に呼び出されていない場合、または大量のデータを返さない場合、このヒットは無視できる可能性があります。

参照:

于 2013-05-08T18:09:27.407 に答える