C++ Dll【应用】

以下内容转自:http://blog.csdn.net/yysdsyl/article/details/2626033

前言:为了介绍C#写界面,C++写算法的快捷开发方式,C#与C++的交互,首先介绍c++,C#内部的DLL,COM调用。

一, 静态的Lib:静态的lib经过编译后只有.h和.lib文件,没有dll,因为实现部分也包含在lib中,这就是与动态dll的区别。还有在写静态lib的时候不需要在使用导出关键字_declspec(dllexport)。一般有2中方法调用静态lib,如下实例:

静态lib:CPPLib->test.h

#pragma once

class CTest
{
public :
    CTest(void);
public :
    ~CTest(void);
public :
   
int Add( int x, int y);
   
int Square( int x);
};

// 函数的实现必须写在.cpp文件中,否则编译有错,说重复定义
int Max( int x, int y);


 

静态lib的实现文件: CPPLib->test.cpp

#include " StdAfx.h "
#include
" Test.h "

CTest::CTest(void)
{
}

CTest::~CTest(void)
{
}

int CTest::Add( int x, int y)
{
return x
+ y;
}
int CTest::Square( int x)
{
    return x
* x;
}

int Max( int x, int y)
{
    return x;
}


client调用CPPLibClient->CPPibClient.cpp

#include " stdafx.h "
// #include " test.h "
// #include < windows.h >
// #include < string >
// #include < assert.h >


// #include " ../CppLib/test.h "
// #pragma comment(lib, " ../debug/CppLib.lib " )
// #pragma 使用法


// #include " test.h "
// 修改编译选项调用静态库
// 需要修改:include的path,lib的path,和加入lib的名字,如下:
// C ++-> General -> additional include directories
// Linker -> General -> additional library directories
// linker -> input -> additional dependencies

// 不能动态加载静态的lib库
// HMODULE m_handle = LoadLibrary(L " ../debug/CppLib.Lib " );
// GetProcAddress(m_handle, " Max " );
// FreeLibrary(m_handle);

int _tmain( int argc, _TCHAR * argv[])
{
    CTest test;
   
int a = test.Add( 10 , 20 );
    printf(
" the result is :%d/n " ,a);
    a
= Max( 10 , 20 );
    printf(
" the result is :%d/n " ,a);
    return
0 ;
   
}


调用方法:可以看出对于静态的只可以使用修改编译选项和pragma comment()来调用,不能使用loadlibrary()来调用。

二 ,动态DLL:在动态dll中,可以导出变量,函数和整个类。编译后有.h,.lib和dll文件,真正的实现包含在dll中,所以在client调用动态dll的时候,必须要使用dll,最后和client的放在同意目录下。要导出必须使用导出关键字_declspec(dllexport)。有时还使用extern “C”,为了使导出能够与C兼容,一般我们都加extern “c”。
一般调用有3中方法,实例如下:

实例1:演示了导出变量和函数,和前2中调用方法,修改编译选项和pragma comment().
动态dll:CPPdll->test.h

#pragma once


extern
" C " _declspec(dllexport) int nCppDll;
extern
" C " _declspec(dllexport) int fnCppDll(void);

extern
" C " _declspec(dllexport) int Max( int a, int b);
extern
" C " _declspec(dllexport) int Min( int a, int b);


动态dll的实现:CPPDLL->test.cpp

#include " StdAfx.h "
#include
" Test.h "


// This is an example of an exported variable
int nCppDll = 100 ;

// This is an example of an exported function .
int fnCppDll(void)
{
    return
42 ;
}

int Max( int a, int b)
{
if (a >= b)return a;
else
return b;
}
int Min( int a, int b)
{
if (a >= b)return b;
else
return a;
}


client的调用:cppclient->cppclient.cpp

#include " stdafx.h "

#pragma comment(lib,
" ../debug/CppDll.lib " )
extern
" C "   int Max( int a, int b); // _declspec(dllimport)
extern
" C " int Min( int a, int b); // _declspec(dllimport)
extern
" C " _declspec(dllimport) int nCppDll;
extern
" C " int fnCppDll(void);

// #include " test.h "
// 修改编译选项调用静态库
// 需要修改:include的path,lib的path,和加入lib的名字,如下:
// C ++-> General -> additional include directories
// Linker -> General -> additional library directories
// linker -> input -> additional dependencies

int _tmain( int argc, _TCHAR * argv[])
{
   
int a;
    a 
= Min( 8 , 10 );
    printf(
" 比较的结果为 %d/n " ,a);
    a
= Max( 8 , 10 );
    printf(
" 比较的结果为%d/n " ,a);
   
    printf(
" 导出的变量:%d/n " ,nCppDll);

    a
= fnCppDll();
    printf(
" fnCppDll的结果:%d/n " ,a);   

    return
0 ;
}

上面演示了对一般变量和函数的导出的调用方法中的其中的2中,修改编译选项和pragma comment(),当使用pragma comment()的使用,应当注意:
使用#pragma隐式加载动态库
对于变量,必须申明且不能include头文件。extern "C" _declspec(dllimport) int nCppDll;
对于函数,或include头文件,或是申明。extern "C" int fnCppDll(void);
对于类,最好使用函数封装导出指针供使用。
参考:http://www.cppblog.com/mzty/archive/2006/07/24/10419.html

实例2:演示类的导出和使用动态加载来调用。

动态dll的类导出:CPPDll2->test.h

#pragma  once
// #include " boost/shared_ptr.hpp "

class Test
{
public :
virtual ~Test() {}
virtual void DoIt()
= 0 ;
};

// extern " C " _declspec(dllexport)  std::auto_ptr < Test > CreateTest();
// extern " C " _declspec(dllexport) boost::shared_ptr < Test > CreateTest();
extern
" C " _declspec(dllexport) Test * CreateTestPtr();

extern
" C " _declspec(dllexport) void DeleteTestPtr(Test * );


动态dll的类导出的实现:CPPDll2->test.cpp

// test.cpp
#include
" stdafx.h "
#include
" Test.h "
#include
< stdio.h >
// #include < memory >
// #include " boost/shared_ptr.hpp "


class CTest :
public Test
{
public :
    virtual void DoIt()
   { printf(
" Should do something/n " ); }
};

// std::auto_ptr < Test > CreateTest()
// {
//     return std::auto_ptr < Test > ( new CTest);
// }


// boost::shared_ptr < Test > CreateTest()
// {
//     return boost::shared_ptr < Test > ( new CTest); 
// }

Test
* CreateTestPtr()
{
    return
new CTest();
}

void DeleteTestPtr(Test
* t)
{
   
if (t ! = NULL )
    {
        delete t;
        t
= NULL ;
    }

}

对loadlibrary的分装,可以作为tools:

// library.h
#pragma once
#include
< windows.h >
#include
< string >
#include
< assert.h >

class Library
{
public :

explicit Library( const wchar_t * name)
{
  m_handle
= LoadLibrary(name);
  assert(m_handle);
 
if (!m_handle)
   throw std::runtime_error(std::
string ( " Could not find library file: " )); 
}

~Library()
{
  FreeLibrary(m_handle);
}

void
* GetProc( const char * name)
{
  void
* proc = ::GetProcAddress(m_handle, name);
  assert(proc);
  return proc;
}

private :
HMODULE m_handle;
};


client的调用:


#include
" stdafx.h "
#include
" library.h "
#include
" ../CppDll2/test.h "

int _tmain( int argc, _TCHAR * argv[])
{
   
    typedef Test
* ( * CREATE)();
    typedef void (
* DEL)(Test * );   

    Library lib(L
" CppDll2.dll " );
   
// std::auto_ptr < Test > test = ((std::auto_ptr < Test > ) lib.GetProc( " CreateTest " ));
    Test
* test = (((CREATE)(lib.GetProc( " CreateTestPtr " )))());
    test
-> DoIt();
    ((DEL)(lib.GetProc(
" DeleteTestPtr " )))(test);
    return
0 ;
}


上面的是对类的动态调用,注意需要include头文件哦!
//通过API动态加载动态库
//对于类的导出,最好使用函数封装,导出类的指针。
//动态加载dll, 如果导出的函数只使用 extern,而没有使用extern "C" 则GetProcAdress会找不到函数的指针,要想找到可以使用真正要找的函数原型哦,可能是函数名后加@@。。。,也可以使用编号来找到需要的函数地址。
//但是如果导出函数使用extern "C"的话,导出函数的返回值不能是auto_ptr<>或shared_ptr<>哦,但是我们仍然可以使用智能指针哦,采用的方法是不使用return返回,使用函数的参数返回哦。//使用智能指针导出的更好的实现,请参考 http://www.cppblog.com/eXile

//参考: http://www.cppblog.com/eXile/archive/2007/04/19/22262.html

//更多dll类型:http://www.vckbase.com/document/viewdoc/?id=1116

//调用约定:http://blog.chinaunix.net/u/21790/showart_265932.html


三 资源DLL

在C++中,我们可以建立纯资源的动态dll,比如说我们建立了一个动态的资源dll,里面增加一个string: id为IDS_APPLICATION,值为:aaa,
则我们可以在client动态调用如下:

#include " stdafx.h "
#include
< windows.h >
#include
" ../ResDll/resource.h "

int _tmain( int argc, _TCHAR * argv[])
{
    HMODULE hModule
= LoadLibrary(L " ../debug/ResDll.dll " );
   
if ( NULL ! = hModule)
    {
        TCHAR szName[
200 ];
        ::LoadString(hModule,IDS_APPLICATION,szName,
200 );
        FreeLibrary(hModule);
    }
    return
0 ;
}


资源还可以是其他的比如是icon,bitmap。。。。等,有对应的load。()函数去调用。

四,总结

熟悉dll调用的3中方法,其中对静态的调用只有2中方法,一般对类的导出调用要使用函数封装哦!:~

 

 

以下内容转自:http://blog.csdn.net/yysdsyl/article/details/2626109

c++动态加载dll中的类(用于实现依据字符串类名创建对象)

参考资料:

http://blog.csdn.net/yysdsyl/archive/2008/07/08/2626033.aspx

用来生成dll的文件:

  1. Test.h 
  2.  
  3. class Test 
  4.  
  5.  
  6. public
  7.  
  8.     Test(void); 
  9.  
  10. public
  11.  
  12.     virtual ~Test(void); 
  13.  
  14. public
  15.  
  16.     virtual void DoSth()=0; 
  17.  
  18. }; 
Test.h

class Test

{

public:

    Test(void);

public:

    virtual ~Test(void);

public:

    virtual void DoSth()=0;

};

--------------------------------------------

  1. ///TTest.h 
  2.  
  3. /TTest继承自Test 
  4.  
  5. class TTest : 
  6.  
  7.     public Test 
  8.  
  9.  
  10. public
  11.  
  12.     TTest(void); 
  13.  
  14. public
  15.  
  16.     ~TTest(void); 
  17.  
  18. public
  19.  
  20.     virtual void DoSth(){std::cout<<"TTest:do sth/n";}; 
  21.  
  22. }; 
///TTest.h

/TTest继承自Test

class TTest :

    public Test

{

public:

    TTest(void);

public:

    ~TTest(void);

public:

    virtual void DoSth(){std::cout<<"TTest:do sth/n";};

};
  1. ///关键 
  2.  
  3.  
  4.  
  5.  
  6.  
  7. extern "C" __declspec(dllexport) Test* CreateTTestPtr(); 
  8.  
  9. extern "C" __declspec(dllexport) void DeleteTTestPtr(Test* t); 
///关键





extern "C" __declspec(dllexport) Test* CreateTTestPtr();

extern "C" __declspec(dllexport) void DeleteTTestPtr(Test* t);

--------------------------------------------------

  1. TTest.cpp 
  2. #include "TTest.h" 
  3.  
  4.  
  5.  
  6. TTest::TTest(void
  7.  
  8.  
  9.  
  10.  
  11.  
  12. TTest::~TTest(void
  13.  
  14.  
  15.     std::cout<<"destruct TTest/n"
  16.  
  17.  
  18.  
  19.  
  20. Test* CreateTTestPtr() 
  21.  
  22.  
  23.     return new TTest(); 
  24.  
  25.  
  26.  
  27.  
  28. void DeleteTTestPtr(Test* t) 
  29.  
  30.  
  31.     if(t!=NULL) 
  32.  
  33.         delete t; 
  34.  
TTest.cpp

#include "TTest.h"



TTest::TTest(void)

{

}



TTest::~TTest(void)

{

    std::cout<<"destruct TTest/n";

}



Test* CreateTTestPtr()

{

    return new TTest();

}



void DeleteTTestPtr(Test* t)

{

    if(t!=NULL)

        delete t;

}
  1. 测试程序: 
测试程序:
  1. <pre class="csharp" name="code">#include "Test.h" 
  2. #include <Windows.h> 
  3.  
  4.  
  5.  
  6. typedef Test* (CREATEFN)(); 
  7.  
  8. typedef void (DELETEFN)(Test* ); 
  9.  
  10.  
  11.  
  12.  
  13.  
  14. int _tmain(int argc, _TCHAR* argv[]) 
  15.  
  16.  
  17.     HINSTANCE hd=::LoadLibrary("AnotherDll.dll"); 
  18.  
  19.  
  20.  
  21.     CREATEFN* pfn; 
  22.  
  23.     DELETEFN* xfn; 
  24.  
  25.  
  26.  
  27.     pfn=(CREATEFN *)::GetProcAddress(hd,"CreateTTestPtr"); 
  28.  
  29.     xfn=(DELETEFN *)::GetProcAddress(hd,"DeleteTTestPtr"); 
  30.  
  31.      
  32.  
  33.     Test* t=(*pfn)(); 
  34.  
  35.     t->DoSth(); 
  36.  
  37.     (*xfn)(t); 
  38.  
  39.  
  40.  
  41.     getchar(); 
  42.  
  43.     return 0; 
  44.  
  45. </pre> 
  46. <pre class="csharp" name="code"> </pre> 
  47. <pre class="csharp" name="code"> </pre> 
  48. <pre class="csharp" name="code"> </pre> 
  49. <pre class="csharp" name="code">-------------------------------------------------------------------</pre> 
  50. <pre class="csharp" name="code"> </pre> 
  51. <pre class="csharp" name="code">向dll中添加新的继承于Test基类时,实现自身的同时实现下面的两函数</pre> 
  52. <pre class="csharp" name="code"
  53.  
  54.  
  55. extern "C" __declspec(dllexport) Test* CreateXXXPtr(); 
  56.  
  57. extern "C" __declspec(dllexport) void DeleteXXXPtr(Test* t);</pre> 
  58. <pre class="csharp" name="code"> </pre> 
  59. <pre class="csharp" name="code">(其中XXX表示新添加的类的类名,当然命名可以随意,只要你能在应用程序中找到这两导出函数,不过统一的命名规则</pre> 
  60. <pre class="csharp" name="code">对根据类名创建对象是有好处的)</pre> 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值