2017-06-01 81 views
0

我假設我在使用dlopen時不必鏈接到共享庫。然而,在cmake的target_link_libraries(main_dlopen dl)導致鏈接錯誤使用dlopen時,我應該鏈接到我打開的庫嗎?

main_dlopen.cpp.o: In function `main': 
main_dlopen.cpp:25: undefined reference to `ntclass::init(char const*)' 
etc... 

如果我使用target_link_libraries(main_dlopen dl ntclass),其中libntclass.so是我的圖書館,然後一切都很好。

它真的很好還是我錯過了什麼?作爲背景,我想測試非線程安全庫,如解釋here,並期望鏈接應避免與非線程安全庫。 以下部分回答我自己

下面是一個完整的例子(使用this作爲參考)。

(共享庫)

ntclass.h

#ifndef NTCLASS_H 
#define NTCLASS_H 

#include <cstddef> 

class ntclass 
{ 
    private: 
    static char *sptr; 
    char *ptr; 

    public: 
    ntclass() : ptr(NULL) {} 
    ~ntclass(); 

    void init(const char* str); 
    void print(); 
}; 

typedef ntclass* create_t(); 

#endif // NTCLASS_H 

ntclass.cpp

#include "ntclass.h" 
#include <stdio.h> 
#include <string.h> 
#include <iostream> 

char *gptr = NULL; 

char *ntclass::sptr = NULL; 

ntclass::~ntclass() 
{ 
    if (gptr) 
    { 
    delete[] gptr; 
    gptr = NULL; 
    } 
    if (sptr) 
    { 
    delete[] sptr; 
    sptr = NULL; 
    } 
    if (ptr) 
    { 
    delete[] ptr; 
    ptr = NULL; 
    } 
} 

void ntclass::init(const char* str) 
{ 
    int size = strlen(str)*sizeof(char); 
    gptr = new char[size]; 
    memcpy(gptr, str, size); 
    sptr = new char[size]; 
    memcpy(sptr, str, size); 
    ptr = new char[size]; 
    memcpy(ptr, str, size); 
} 

void ntclass::print() 
{ 
    std::cout << "Global: " << gptr << std::endl; 
    std::cout << "Static: " << sptr << std::endl; 
    std::cout << "Normal: " << ptr << std::endl; 
} 

extern "C" ntclass *create() 
{ 
    return new ntclass(); 
} 

(主可執行文件)

main_dlopen.cpp

#include <iostream> 
#include "ntclass.h" 

#include <dlfcn.h> 
#include <stdlib.h> 

using namespace std; 

int main() 
{ 
    void *handle = dlopen("./libntclass.so", RTLD_NOW); 

    if (handle == NULL) 
    { 
    cerr << dlerror() << endl; 
    exit(-1); 
    } 

    create_t *createA = (create_t*) dlsym(handle, "create"); 
    create_t *createB = (create_t*) dlsym(handle, "create"); 

    ntclass *A = createA(); 
    ntclass *B = createB(); 

    A->init("A"); 
    B->init("B"); 

    A->print(); 
    B->print(); 

    delete A; 
    delete B; 

    return 0; 
} 

(CMake的)

cmake_minimum_required(VERSION 2.8) 

set(CMAKE_VERBOSE_MAKEFILE on) 
set(CMAKE_BUILD_TYPE RelWithDebInfo) 

add_library(ntclass SHARED ntclass.cpp) 

add_executable(main_dlopen main_dlopen.cpp) 
target_link_libraries(main_dlopen dl) # <-- Here is a problem 

部分答案: 我添加關鍵字virtual爲ntclass方法(INIT,打印〜ntclass),現在工作得很好。不過,任何人都可以解釋爲什麼它需要?

回答

1

你的「部分答案」是一個正確的解決方案。有關說明,請參見that nice answer關於virtual的關鍵字。

簡而言之:

直到在ntclassinit方法聲明爲虛擬,表達

A->init("A") 

使用方法的定義在該類(獨立於所實際類型對象A有)。由於main_dlopen.cpp中沒有這個定義,鏈接器會生成錯誤。

隨着virtual關鍵字,init方法的分辨率遞延到運行時,當實際類型A對象將是已知的。

+0

謝謝,現在很清楚。 – Ivan