在C#项目中导入C ++ dll

时间:2017-08-23 09:41:58

标签: c# c++ winapi pinvoke dllimport

我有一个用于监控打印机的C ++ DLL(使用FindFirstPrinterChangeNotification)。我正在为它制作C#Wrapper:

private static class NativeMethods {
        [DllImport("kernel32", SetLastError = true)]
        public static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32", SetLastError = true)]
        public static extern bool FreeLibrary(IntPtr hModule);
}

    public string LibPath;
    private IntPtr LibPtr;
    private GBtMX GBtMain;

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void GBtMX();

    public GhostBuster() {
        LibPath = AppDomain.CurrentDomain.BaseDirectory + @"\GhostBusterC.dll";
    }

    public string Init() {
        if (!File.Exists(LibPath))
            return "Incorrect path " + LibPath;
        LibPtr = NativeMethods.LoadLibrary(LibPath);
        if (LibPtr == IntPtr.Zero)
            return "Couldn't import library. Error(GetLastWin32Error): " + Marshal.GetLastWin32Error().ToString();

        IntPtr GBtMainPtr = NativeMethods.GetProcAddress(LibPtr, "tmain");
        if (GBtMainPtr == IntPtr.Zero)
            return "No access to GhostBuster.tmain.  Error (GetLastWin32Error): " + Marshal.GetLastWin32Error().ToString();
        GBtMain = (GBtMX)Marshal.GetDelegateForFunctionPointer(GBtMainPtr, typeof(GBtMX));            
        return "";

它返回"无法访问GhostBuster.tmain。错误(GetLastWin32Error):0"。 我究竟做错了什么? 提前谢谢。

1 个答案:

答案 0 :(得分:1)

您没有在p / invoke中指定SetLastError,因此Marshal.GetLastWin32Error()无法返回任何有用的内容。 p / invoke应该是

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(
    IntPtr hModule, 
    [MarshalAs(UnmanagedType.LPStr)]
    string lpProcName
);

另请注意,明确有关过程名称的编组是有意义的。这总是一个ANSI字符串,反映了PE格式。

当您进行此更改时,我预计该错误将为ERROR_PROC_NOT_FOUND,表明DLL不会导出任何具有您传递给GetProcAddress的名称的内容。

检查您是否正确拼写了函数名称。你收到了信件案件吗?在构建DLL时是否应用了任何装饰或修改?使用dumpbin或Dependency Walker之类的工具来检查DLL导出的名称。