ubuntu下codeblocks起步(補充篇)-下

CodeBlocks學習 如何編譯多個目標  

呵,說多個目標,還不如說是如何在一個工程中,編譯不同的動態庫。想想MFC中一個動態庫就是一個工程,當動態庫多的時候,覺得管理不是很好,CodeBlocks支持在一個工程中,可以編譯多個動態庫,以下是我的學習體會。

之所以會有這樣的需求,主要是因爲我在用了ECLIPSE之後,覺得其plugin功能真的很強大,再者,CodeBlocks也是基於plugin框架架構的,所以想具體的學習一下,基於wxWidgets的plugin程序框架設計。

在學習過程中,我發現,一個工程一個庫,這個管理不太方便。於是,就想可不可以在同一個工程中,編譯不同的目標動態庫?經過一番摸索,CodeBlocks可以實現我的需求。以下將方法記錄下來,以備查閱。

  1.  創建一個wxStudy工程,增加4個文件到工程, 
//MainApp.h
#ifndef WX_MAIN_APP_H
#define WX_MAIN_APP_H

#include 
<wx/app.h>

class MainApp : public wxApp
{

    
public:
        MainApp();
    
public:
        
virtual bool OnInit();

    
private:
        
void InitFrame();

}
;

DECLARE_APP(MainApp)
#endif

 

//MainApp.cpp


#include 
"mainApp.h"

#include 
"MainFrame.h"


IMPLEMENT_APP(MainApp)


MainApp::MainApp()
{
}


bool MainApp::OnInit()
{
    InitFrame();
    
return true;
}


void MainApp::InitFrame()
{
    MainFrame
* pMainFrm = new MainFrame(_T("MainFrame"));
    pMainFrm
->Show(true);
}

 

//MainFrame.h

#ifndef MAIN_FRAME_H
#define MAIN_FRAME_H

#include 
<wx/frame.h>
//#include <wx/wx.h>

class MainFrame : public wxFrame
{
    
public:
        MainFrame(
const wxString& strTitle);

    
private:
        
void InitCtrl();

    
private://event
        void OnAbout(wxCommandEvent& event);
        
void OnQuit(wxCommandEvent& event);

        
//測試動態庫
        void OnShowMessage(wxCommandEvent& event);
    
private:
        DECLARE_EVENT_TABLE()
}
;
#endif

 

//MainFrame.cpp

#include 
"MainFrame.h"

#include 
<wx/menu.h>
//#include <wx/string.h>
#include <wx/msgdlg.h>
#include 
<wx/dynlib.h>
#include 
<wx/filefn.h>
#include 
<wx/filename.h>

#include 
"maindef.h"
//EVENT DECLARE
BEGIN_EVENT_TABLE(MainFrame,wxFrame)

    EVT_MENU(wxID_EXIT,MainFrame::OnQuit)
    EVT_MENU(wxID_ABOUT,MainFrame::OnAbout)
    EVT_MENU(wxID_TEST_DLL,MainFrame::OnShowMessage)
END_EVENT_TABLE()

//END EVENT DECLARE

MainFrame::MainFrame(
const wxString& strTitle)
:wxFrame(NULL,wxID_ANY,strTitle)
{
    InitCtrl();
}



void MainFrame::InitCtrl()
{

    wxMenu
* pMenu = new wxMenu();
    pMenu
->Append(wxID_EXIT,_T("Exit"));
    pMenu
->Append(wxID_ABOUT,_T("About"));
    pMenu
->Append(wxID_TEST_DLL,_T("測試動態庫"));

    wxMenuBar
* pMenuBar = new wxMenuBar();
    pMenuBar
->Append(pMenu,_T("File"));


    SetMenuBar(pMenuBar);

}


/*
*   退出程序
*   @param wxCommandEvent& event
*/

void MainFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}


void MainFrame::OnAbout(wxCommandEvent& event)
{

    wxString strMsg(_T(
"wxWidgets study."));
    wxString strCaption(_T(
"關於"));
    wxMessageBox(strMsg, strCaption, wxOK 
| wxICON_INFORMATION,this);


    
//wxMessageBox("Quit program?", "Confirm",wxYES_NO | wxCANCEL, this);

}


void MainFrame::OnShowMessage(wxCommandEvent& event)
{

    
//wxString dir(wxGetWorkingDirectory());
    
//wxMessageBox(dir,_T("dir"),wxOK);

    wxChar name[MAX_PATH] 
= {0};
    GetModuleFileName(
0L, name, MAX_PATH);
    
//wxMessageBox(name,_T("dir"),wxOK);
    wxFileName fname(name);
    wxString strPath(fname.GetPath(wxPATH_GET_VOLUME));
    wxDynamicLibrary lib;
    wxString libfile(strPath 
<< _T("/plugins/msgplugin/msgplugin.dll"));
    lib.Load(libfile);
    
if(!lib.IsLoaded())
    
{
        wxMessageBox(libfile 
<< _T(" load error."),_T("Error"),wxOK | wxICON_ERROR);
        
return;
    }



    typedef 
int (*ShowMessageProc)(const wxString&);

    ShowMessageProc ShowMessage 
= (ShowMessageProc)lib.GetSymbol(_T("ShowMessage"));
    
if(NULL == ShowMessage)
    
{
        wxMessageBox(_T(
"don't call the method: ShowMessag"), _T("Error"),
            wxOK 
| wxICON_ERROR);
        
return;
    }


    ShowMessage(_T(
"call from "+ libfile);
}

 2.創建動態庫所需要的文件src/plugins/msgplugin/msh.h;src/plugins/msgplugin/msh.cpp 

//msg.h

#ifndef MSG_H_INCLUDED
#define MSG_H_INCLUDED

#include 
"../pluginset.h"
#include 
<wx/string.h>

BEGIN_EXPORT_LANGUAGE()

int PLUGIN_EXPORT ShowMessage(const wxString& msg);

END_EXPORT_LANGUAGE()
#endif // MSG_H_INCLUDED

 

//msg.cpp

#include 
"msg.h"
#include 
<wx/msgdlg.h>

int ShowMessage(const wxString& msg)
{
    wxMessageBox(msg,_T(
"msg"));
    
return 0;
}

3.設置編譯目標 ,File->new -> build target...,如下圖所示:

選擇 Dynamic Link library,編譯動態庫,點GO,next,如下圖:

輸入msgplugin後,點Finish,這樣我們就創建了一個編譯目標,但這還不夠,因爲,還沒有爲此目標增加任何的源文件,接下來,增加源文件。

 在工程樹上點右鍵,選擇Properties->Build targets選項卡,如下圖,你會看到我們輸入的編譯目標(debug_msgplugin):

在build target files中,選擇我們的源文件,如下圖:

呵,離成功還差一步了,接下來,我們要做的就是定義__declspec(__dllexport)或是__dllimport,爲什麼了,在工程中,我們增加一個pluginset.h的文件,文件內容如下:

//pluginset.h

#ifndef PLUGINSET_H
#define PLUGINSET_H

//windows平臺下,動態庫的前輟定義
#ifdef __WXMSW__
    #ifndef PLUGIN_EXPORT
        #ifdef EXPORT_LIB
            
#define PLUGIN_EXPORT __declspec(__dllexport)
        
#else // !EXPORT_LIB
            
#if BUILDING_PLUGIN
                
#define PLUGIN_EXPORT __declspec(__dllexport)
            
#else // !BUILDING_PLUGIN
                
#define PLUGIN_EXPORT __declspec(__dllimport)
            
#endif // BUILDING_PULGIN
        
#endif // EXPORT_LIB
    
#endif // PLUGIN_EXPORT
#else
    
#define PLUGIN_EXPORT
#endif

//導出方式是c方式還是c++方式

#ifdef PLUGIN_EXPORT_C
    
#define BEGIN_EXPORT_LANGUAGE() extern "C" {
    
#define END_EXPORT_LANGUAGE()   }
#else
    
#define BEGIN_EXPORT_LANGUAGE()
    
#define END_EXPORT_LANGUAGE()
#endif

#endif // PLUGINSET_H

定義要導出的方法,如下:

#ifndef MSG_H_INCLUDED
#define MSG_H_INCLUDED

#include 
"../pluginset.h"
#include 
<wx/string.h>

BEGIN_EXPORT_LANGUAGE()

int PLUGIN_EXPORT ShowMessage(const wxString& msg);

END_EXPORT_LANGUAGE()
#endif // MSG_H_INCLUDED

好了,我們可以編譯了,但是在編譯之前,我們來分析一下,pluginset.h中的定義:

//windows平臺下,動態庫的前輟定義
#ifdef __WXMSW__
    #ifndef PLUGIN_EXPORT
        #ifdef EXPORT_LIB
            #define PLUGIN_EXPORT __declspec(__dllexport)
        #else // !EXPORT_LIB
            #if BUILDING_PLUGIN
                #define PLUGIN_EXPORT __declspec(__dllexport)
            #else // !BUILDING_PLUGIN
                #define PLUGIN_EXPORT __declspec(__dllimport)
            #endif // BUILDING_PULGIN
        #endif // EXPORT_LIB
    #endif // PLUGIN_EXPORT
#else
    #define PLUGIN_EXPORT
#endif

……如果定義了BUILDING_PLUGIN,則以動態庫的方式導出……

//導出方式是c方式還是c++方式

#ifdef PLUGIN_EXPORT_C
    #define BEGIN_EXPORT_LANGUAGE() extern "C" {
    #define END_EXPORT_LANGUAGE()   }
#else
    #define BEGIN_EXPORT_LANGUAGE()
    #define END_EXPORT_LANGUAGE()
#endif

如果定義了PLUGIN_EXPORT_C,則以C的方式輸出

所以,我們還要在設置一下編譯器的選項,如下:點右鍵->properties->build target -> build options ,如下圖,選擇debug_msgplugin在#defines中,輸入 BUILDING_PLUGIN,PLUGIN_EXPORT_C,好的,至此爲止,我們的動態庫就可以編譯了

編譯,如下圖:選擇debug_msgplugin

接着build就可以了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章