Linux의 C ++ 동적 공유 라이브러리
이것은 g ++을 사용한 Dynamic Shared Library 컴파일에 대한 후속 조치 입니다.
Linux에서 C ++로 공유 클래스 라이브러리를 만들려고합니다. 라이브러리를 컴파일 할 수 있으며 here 및 here 에서 찾은 자습서를 사용하여 (비 클래스) 함수 중 일부를 호출 할 수 있습니다 . 라이브러리에 정의 된 클래스를 사용하려고하면 문제가 시작됩니다. 내가 링크 한 두 번째 튜토리얼은 라이브러리에 정의 된 클래스의 객체를 생성하기위한 심볼을로드하는 방법을 보여 주지만 해당 객체를 사용하여 작업을 완료하는 데는 부족 합니다.
누구든지 별도의 실행 파일에서 해당 클래스 를 사용 하는 방법을 보여주는 공유 C ++ 클래스 라이브러리를 만드는 더 완벽한 자습서를 알고 있습니까? 객체 생성, 사용 (간단한 게터 및 세터가 훌륭함) 및 삭제가 환상적으로 보이는 매우 간단한 자습서입니다. 공유 클래스 라이브러리 사용을 보여주는 오픈 소스 코드에 대한 링크 또는 참조도 동일합니다.
codelogic 과 nimrodm 의 답변이 효과가 있지만 이 질문을 한 이후 Beginning Linux Programming 의 사본을 선택 했으며 첫 번째 장에는 예제 C 코드와 정적 라이브러리와 공유 라이브러리를 만들고 사용하는 데 대한 좋은 설명이 있습니다. . 이 예는 해당 도서 의 이전 버전 에서 Google 도서 검색을 통해 제공됩니다 .
myclass.h
#ifndef __MYCLASS_H__
#define __MYCLASS_H__
class MyClass
{
public:
MyClass();
/* use virtual otherwise linker will try to perform static linkage */
virtual void DoSomething();
private:
int x;
};
#endif
myclass.cc
#include "myclass.h"
#include <iostream>
using namespace std;
extern "C" MyClass* create_object()
{
return new MyClass;
}
extern "C" void destroy_object( MyClass* object )
{
delete object;
}
MyClass::MyClass()
{
x = 20;
}
void MyClass::DoSomething()
{
cout<<x<<endl;
}
class_user.cc
#include <dlfcn.h>
#include <iostream>
#include "myclass.h"
using namespace std;
int main(int argc, char **argv)
{
/* on Linux, use "./myclass.so" */
void* handle = dlopen("myclass.so", RTLD_LAZY);
MyClass* (*create)();
void (*destroy)(MyClass*);
create = (MyClass* (*)())dlsym(handle, "create_object");
destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object");
MyClass* myClass = (MyClass*)create();
myClass->DoSomething();
destroy( myClass );
}
Mac OS X에서 다음을 사용하여 컴파일하십시오.
g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so
g++ class_user.cc -o class_user
Linux에서 다음을 사용하여 컴파일하십시오.
g++ -fPIC -shared myclass.cc -o myclass.so
g++ class_user.cc -ldl -o class_user
이것이 플러그인 시스템 인 경우 MyClass를 기본 클래스로 사용하고 필요한 모든 기능을 가상으로 정의합니다. 하고자 다음 MyClass의에서 파생 플러그인 저자는 virtuals에를 무시하고 구현 create_object
하고 destroy_object
. 기본 응용 프로그램은 어떤 식 으로든 변경할 필요가 없습니다.
The following shows an example of a shared class library shared.[h,cpp] and a main.cpp module using the library. It's a very simple example and the makefile could be made much better. But it works and may help you:
shared.h defines the class:
class myclass {
int myx;
public:
myclass() { myx=0; }
void setx(int newx);
int getx();
};
shared.cpp defines the getx/setx functions:
#include "shared.h"
void myclass::setx(int newx) { myx = newx; }
int myclass::getx() { return myx; }
main.cpp uses the class,
#include <iostream>
#include "shared.h"
using namespace std;
int main(int argc, char *argv[])
{
myclass m;
cout << m.getx() << endl;
m.setx(10);
cout << m.getx() << endl;
}
and the makefile that generates libshared.so and links main with the shared library:
main: libshared.so main.o
$(CXX) -o main main.o -L. -lshared
libshared.so: shared.cpp
$(CXX) -fPIC -c shared.cpp -o shared.o
$(CXX) -shared -Wl,-soname,libshared.so -o libshared.so shared.o
clean:
$rm *.o *.so
To actual run 'main' and link with libshared.so you will probably need to specify the load path (or put it in /usr/local/lib or similar).
The following specifies the current directory as the search path for libraries and runs main (bash syntax):
export LD_LIBRARY_PATH=.
./main
To see that the program is linked with libshared.so you can try ldd:
LD_LIBRARY_PATH=. ldd main
Prints on my machine:
~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main
linux-gate.so.1 => (0xb7f88000)
libshared.so => ./libshared.so (0xb7f85000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000)
libm.so.6 => /lib/libm.so.6 (0xb7e4e000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000)
libc.so.6 => /lib/libc.so.6 (0xb7cfa000)
/lib/ld-linux.so.2 (0xb7f89000)
Basically, you should include the class' header file in the code where you want to use the class in the shared library. Then, when you link, use the '-l' flag to link your code with the shared library. Of course, this requires the .so to be where the OS can find it. See 3.5. Installing and Using a Shared Library
Using dlsym is for when you don't know at compile time which library you want to use. That doesn't sound like it's the case here. Maybe the confusion is that Windows calls the dynamically loaded libraries whether you do the linking at compile or run-time (with analogous methods)? If so, then you can think of dlsym as the equivalent of LoadLibrary.
If you really do need to dynamically load the libraries (i.e., they're plug-ins), then this FAQ should help.
On top of previous answers, I'd like to raise awareness about the fact that you should use the RAII (Resource Acquisition Is Initialisation) idiom to be safe about handler destruction.
Here is a complete working example:
Interface declaration: Interface.hpp
:
class Base {
public:
virtual ~Base() {}
virtual void foo() const = 0;
};
using Base_creator_t = Base *(*)();
Shared library content:
#include "Interface.hpp"
class Derived: public Base {
public:
void foo() const override {}
};
extern "C" {
Base * create() {
return new Derived;
}
}
Dynamic shared library handler: Derived_factory.hpp
:
#include "Interface.hpp"
#include <dlfcn.h>
class Derived_factory {
public:
Derived_factory() {
handler = dlopen("libderived.so", RTLD_NOW);
if (! handler) {
throw std::runtime_error(dlerror());
}
Reset_dlerror();
creator = reinterpret_cast<Base_creator_t>(dlsym(handler, "create"));
Check_dlerror();
}
std::unique_ptr<Base> create() const {
return std::unique_ptr<Base>(creator());
}
~Derived_factory() {
if (handler) {
dlclose(handler);
}
}
private:
void * handler = nullptr;
Base_creator_t creator = nullptr;
static void Reset_dlerror() {
dlerror();
}
static void Check_dlerror() {
const char * dlsym_error = dlerror();
if (dlsym_error) {
throw std::runtime_error(dlsym_error);
}
}
};
Client code:
#include "Derived_factory.hpp"
{
Derived_factory factory;
std::unique_ptr<Base> base = factory.create();
base->foo();
}
Note:
- I put everything in header files for conciseness. In real life you should of course split your code between
.hpp
and.cpp
files. - To simplify, I ignored the case where you want to handle a
new
/delete
overload.
Two clear articles to get more details:
참고URL : https://stackoverflow.com/questions/496664/c-dynamic-shared-library-on-linux
'IT' 카테고리의 다른 글
CSS 표시 속성을 기본값으로 재설정 (0) | 2020.06.02 |
---|---|
.NET 4.0에서 Microsoft.csharp.dll은 (는) 무엇 이죠 (0) | 2020.06.02 |
언제 WeakHashMap 또는 WeakReference를 사용 하시겠습니까? (0) | 2020.06.02 |
전체 객체 또는 컨테이너에 객체에 대한 포인터를 저장해야합니까? (0) | 2020.06.02 |
안드로이드가 프로세스를 죽이는 것을 시뮬레이션하는 방법 (0) | 2020.06.02 |