2017-06-01 84 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