获取.NET中非托管dll导出的char *的值

时间:2011-09-08 08:13:42

标签: c# .net pinvoke

我试图获取非托管dll导出的字符串的值。

dll中的字符串声明为

extern "C" __declspec(dllexport) const char* _Version = "0.1";

我用来获取值的代码如下。我从调用GetProcAddress获取变量的地址,但Marshal.PtrToStringAuto返回垃圾...

怎么了?

    public string GetDllVersion()
    {
            IntPtr lib = LoadLibrary(@"some.dll");
            if(lib == IntPtr.Zero)
                    throw new Win32Exception(Marshal.GetLastWin32Error());

            IntPtr procAddress = GetProcAddress(lib, "_Version");
            var ver2 = Marshal.PtrToStringAuto(procAddress);

            if(!FreeLibrary(lib))
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            return ver2;
    }

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FreeLibrary(IntPtr hModule);

3 个答案:

答案 0 :(得分:4)

你必须在这里使用Marshal.PtrToStringAnsi()。

“自动”表示“操作系统默认”。使用Windows 98和ME在濒危物种列表中,这很可能是您计算机上的Unicode。你的字符串不是const wchar_t *。

答案 1 :(得分:4)

这是我的解决方案;检查它,它的工作原理。

IntPtr procAddress = GetProcAddress(lib, "_Version");
IntPtr verAddress = Marshal.ReadIntPtr(procAddress);
var ver2 = Marshal.PtrToStringAnsi(verAddress);

答案 2 :(得分:3)

通过取消引用GetProcAddress:

中的指针来解决此问题
procAddress = Marshal.ReadIntPtr(GetProcAddress(lib, "_Version"));

还改变了Hans Passant的每个建议读取字符串的方式(其他答案):

var ver2 = Marshal.PtrToStringAnsi(procAddress);