我正在编写一个 .NET 应用程序来调用非托管 DLL。
下面是非托管 DLL 的标头:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// Callback function for ProcessFileAPI. The function is called whenever progress advances.
typedef VOID (CALLBACK* LPPROGRESSPROC)(CONST BYTE btProgress, LPVOID lParam);
#pragma pack(1)
// Options for ProcessFileAPI
typedef struct _OPTIONS1
{
BOOL m_bOption1;
BOOL m_bOption2;
} OPTIONS1, *LPOPTIONS1;
#pragma pack()
DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1);
#ifdef __cplusplus
}
#endif
以及非托管 DLL 的 .cpp:
extern "C" DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1)
{
TRACE(_T("SrcFileName: %s. DstFileName: %s."), lpSrcFileName, lpDstFileName);
return 0;
}
以下是该函数的 .NET 代码:
using System;
using System.Runtime.InteropServices;
namespace SDKAPI
{
public struct TOptions1
{
public bool bOption1;
public bool bOption2;
} // end TOptions1
public delegate void TProgressProc(byte btProgress, IntPtr lParam);
}
namespace SDKAPI.Units
{
public class SDKAPI
{
[DllImport("SDK.DLL")]
public static extern uint ProcessFileAPI(string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc, IntPtr lpProgProcParam, ref int pbCancel, ref TOptions1 options);
} // end SDKAPI
}
下面是函数的调用:
Options1.bOption1 = true;
Options1.bOption2 = false;
// Process the file
FCancel = 0;
RetCode = SDKAPI.Units.SDKAPI.ProcessFileAPI(txtSrcFile.Text, txtDstFile.Text, new SDKAPI.TProgressProc(this.ProgressProc), IntPtr.Zero, ref FCancel, ref Options1);
用
txtSrcFile.Text = "a"
和txtDstFile.Text = "b"
调用DLL时,但我在DLL中调试,发现参数lpSrcFileName
变成了"a"
,后面跟着很多奇怪的字符。为什么?
您需要查明非托管DLL是否使用Unicode。如果是,您需要
CharSet.Unicode
,否则CharSet.Ansi
。
您还需要在
bool
s 上设置包装和编组
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct TOptions1
{
[MarshalAs(UnmanagedType.I1)]
public bool bOption1;
[MarshalAs(UnmanagedType.I1)]
public bool bOption2;
}
[UnmanagedFunctionPointer]
public delegate void TProgressProc(byte btProgress, IntPtr lParam);
[DllImport("SDK.DLL", CharSet = CharSet.Unicode)]
public static extern uint ProcessFileAPI(
string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc,
IntPtr lpProgProcParam, [MarshalAs(UnmanagedType.I1)] ref bool pbCancel,
[In] in TOptions1 options);