WPF C#应用程序中的C ++ Dll

时间:2018-02-13 10:46:54

标签: c# c++ wpf pinvoke dllimport

在寻找已经针对我的类似问题提出的解决方案后, 因为这是我第一次在.NET应用程序中使用非.NET DLL, 我真的需要你的帮助。

我有一个使用MVVM模式的WPF应用程序,在我的ViewModel类中,我需要使用在C ++中完成的DLL来恢复令牌。我在C ++中有一个使用这个DLL的例子,所以我有方法的名字,但我不能在C#中做同样的事情。我知道我必须使用DllImport来使用这个方法,但是如何实现它并在C#中使用指针?

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <string>

int main()
{
    HINSTANCE hinst = NULL;

    typedef bool ( *GetTokenProto )( char ** );
    typedef void ( *FreeTokenProto )( char * );

    GetTokenProto GetToken;
    FreeTokenProto FreeToken;

    std::string str = "DllName.dll";
    std::string token;

    if ( (hinst = LoadLibraryA(str.c_str()) ) )
    {
        GetToken = (GetTokenProto) GetProcAddress(hinst, "GetToken");
        FreeToken = (FreeTokenProto) GetProcAddress(hinst, "FreeToken");

        if (GetToken && FreeToken)
        {
            char *buf;
            if (GetToken(&buf))
            {
                token = buf;
                FreeToken(buf);

                std::cout << "Token:" << token << std::endl;
            }
            else
            {
                std::cerr << "DLL loaded but no token" << std::endl;
                exit(1);
            }
        }
        else
        {
            std::cerr << "DLL loaded but missing proc address(es)" << std::endl;
            exit(1);
        }

        FreeLibrary(hinst);
    }
    else
    {
        std::cerr << "Failed to load DLL" << std::endl;
        exit(1);
    }
    return 0;
}

更新

[DllImport("DllName.dll", EntryPoint = "GetToken", CallingConvention = CallingConvention.Cdecl)] 
public static extern bool get_token(ref string token); 

[DllImport("DllName.dll", EntryPoint = "FreeToken", CallingConvention = CallingConvention.Cdecl)] 
public static extern void free_token(ref string token);

public static string a_token; 
public string get_token_method() 
{ 
    try 
    { 
        string buffer = null; 
        if (get_token(ref buffer)) 
        { 
            a_token = buffer; 
            free_token(ref buffer); 
            Debug.WriteLine("token : " + a_refresh_token); 
        } 
        else 
        { 
            Debug.WriteLine("DLL Loaded but no token"); 
        } 
    } 
    catch (Exception ex) 
    { 
       Debug.WriteLine("\n" + ex.Message); 
    } 
    return a_refresh_token; 
}

错误

  

我有一个例外&#34; System.DllNotFoundException&#34; :无法加载DLL   &#39; DllName.dll&#39;:找不到指定的模块。 (例外   来自HRESULT:0x8007007E)。

Dll文件位于.exe(.. \ bin \ Debug)

的同一文件夹中

3 个答案:

答案 0 :(得分:1)

如果您的DLL位于同一目录中,则仍有一些问题可能存在。

首先

Dll可能有依赖

  

您使用的本机DLL可能还有其他依赖项   已安装(try Dependency Walker)。如果本机DLL需要   示例注册表设置,配置文件等。这些也应该是   当下。它应该以与您相同的方式分发给用户计算机   将它安装在开发机器上。

很可能你错过了C ++可再发行组件包(我不是哪一个),Dependency Walker应该告诉你什么

<强>其次

它可能针对不同的位数,即x86 x64,所以id尝试更改项目以查看是否有帮助

  
      
  • 右键单击您的项目,然后选择属性。

  •   
  • 在属性中,选择构建选项卡。在平台目标下,选择x86。

  •   
  • 按Ctrl + Shift + S保存所有文件,右键单击解决方案并选择“清除”以清除旧的二进制文件。之后的任何构建   应该是32位

  •   

答案 1 :(得分:0)

您可以在调用dll之前使用SetDllDirectory方法设置dll的路径

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetDllDirectory(string lpPathName);

答案 2 :(得分:0)

如果你想从c ++中获取字符串,你还应该在c#端使用StringBuilder而不是string。