C++ 封裝DLL遇到的一些坑爹問題與解決方案

一.string類型不兼容
這個算是最多見也是最初級的問題了,爲了方便跨語言接口調用,若是數據量不是特別大的話,咱們能夠在封裝DLL時選擇json串來做爲方法的引入參數和返回值,但因爲C++的string類型(實際上是STL)內存分配器兼容性很滑稽,基本上跨平臺調用就必定會出現異常。因此要避免在動態庫接口中傳遞STL容器。html

解決方案:
比較常規的方法是使用char *進行指針傳遞,但同時有會存在一個問題,就是返回這個指針以後,調用層還能不能收的到,爲了保證這塊內存不隨着調用方法結束而釋放,咱們能夠採起全局變量等方法。ios

extern "C"
{
    char res[255];
    __declspec(dllexport)  const char * __stdcall change_str(const char* s)
    {
        string ss = s;
        strcpy_s(res, ("change_str::" + ss).c_str());
        return res;
    }        
}
二.x86和x64引發的內存異常json


解決方案:
修改配置函數

三.__stdcall和__cdecl
__stdcall和__cdecl是兩種函數名字修飾。__stdcall和__cdecl函數參數都是從可向左入棧的,而且由調用者完成入棧操做。對於__stdcall方式被調用者自身在函數返回前清空堆棧;而__cdecl則由調用者維護內存堆棧,因此調用者函數生成的彙編代碼比前一種方式長。工具

__stdcall方式:_FuncName@sizeofParametersspa

例如:int __stdcall test(int a,double b)編譯以後完整的函數名爲_test@12.net

__cdecl方式:_FuncName指針

例如:int __stdcall test(int a,double b)編譯以後完整的函數名爲_testhtm

使用VS進行dll開發若是不加修飾符的話,默認是採起__cdecl的方式,__cdecl雖然約定的函數只能被C/C++調用。但其餘語言也是能夠調用的,如delphi。可是C#或者VB的默認方式是__stdcall,因此直接不能直接經過 Public Declare Function add Lib的方式調用。不然會報錯:blog

調用致使堆棧不對稱。緣由多是託管的 PInvoke 簽名與非託管的目標籤名不匹配。請檢查 PInvoke 簽名的調用約定和參數與非託管的目標籤名是否匹配。
解決方案:
有人說能夠經過[DllImport("Dll.dll")]改成[DllImport("Dll.dll", CallingConvention=CallingConvention.Cdecl)]也就是換成Cdecl方式能夠解決

Imports System.Runtime.InteropServices
<DllImport("tset.dll", CallingConvention = CallingConvention.Cdecl)> Private Shared Function add(ByVal a As Integer, ByVal b As Integer) As Integer
End Function
並且DllImport看起來也比Declare要高大上。

https://cloud.tencent.com/info/06698cf1621639b6be6d87fe705a9795.html

可是不知道是否是個人VB版本問題,提示找不到CallingConvention這個屬性,很尷尬。

同時,爲了提升DLL的擴展性,仍是建議使用_stdcall方式來封裝:

extern "C"
{
    __declspec(dllexport) int __stdcall add(int a, int b)
    {
        return a + b;
    }        
}
四.找不到方法的入口點&C++調用GetProcAddress獲取函數指針異常


解決方案:
1.使用工具(例如dependency)查看封裝的DLL是否存在相應的接口

2.若是沒有的話,封裝DLL時能夠導入def文件

EXPORTS下面的名與C++接口對應

LIBRARY "Test"
EXPORTS
add  @1
change_str @2
print_creater @3
#include "stdafx.h"
extern "C"
{
    char res[255];
 
    __declspec(dllexport) int __stdcall add(int a, int b)
    {
        return a + b;
    }
    __declspec(dllexport)  const char * __stdcall change_str(const char* s)
    {
        string ss = s;
        strcpy_s(res, ("change_str::" + ss).c_str());
        return res;
    }
    __declspec(dllexport) const char * __stdcall print_creater()
    {
 
        strcpy_s(res, "nine_sun666");
        return res;
    }
        
}
在項目屬性中導入模塊定義文件便可

VB代碼:

Module Module1
    Public Declare Function add Lib "test.dll" (ByVal a As Integer, ByVal b As Integer) As Integer
    Public Declare Function print_creater Lib "test.dll" () As String
    Public Declare Function change_str Lib "test.dll" (ByVal s As String) As String
 
    Sub Main(ByVal args As String())
        Console.WriteLine("Hello World!")
        Console.WriteLine(add(10, 20))
        Console.WriteLine(print_creater())
        Console.WriteLine(change_str("6666666"))
    End Sub
End Module
調用成功!

五.C++調用約定聲明衝突


解決方案:
仍是因爲默認的導入修飾符爲__cdecl形成的,因此在C++調用層定義類型也要加上__stdcall

pSubtract1 add = pSubtract1(GetProcAddress(hDLL, "add"));        

#include "stdafx.h" #include<iostream> using namespace std; int main() {         HMODULE hDLL = LoadLibrary(_T("test.dll")); //加載dll文件      if (hDLL != NULL)     {             typedef int (__stdcall *pSubtract1)(int a, int b);         pSubtract1 add = pSubtract1(GetProcAddress(hDLL, "add"));                          typedef const char * (__stdcall *pSubtract2)();         pSubtract2 print_creater = pSubtract2(GetProcAddress(hDLL, "print_creater"));                          typedef const char * (__stdcall *pSubtract3)(const char * a);         pSubtract3 change_str = pSubtract3(GetProcAddress(hDLL, "change_str"));           cout << add(10, 20) << endl;         cout << print_creater() << endl;         cout << change_str("hello word") << endl;           FreeLibrary(hDLL);     }     else     {         std::cout << "Cannot Find " << "testdll" << std::endl;     }     system("pause");     return 0; }   ---------------------  做者:九日王朝  來源:CSDN  原文:https://blog.csdn.net/sm9sun/article/details/84986875  版權聲明:本文爲博主原創文章,轉載請附上博文連接!

相關文章
相關標籤/搜索