├── .gitignore ├── Makefile ├── README.md ├── cpp_class.cpp ├── cpp_class.h ├── example_main.c ├── wrapper.cpp └── wrapper.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | # Backups and other 35 | *.DS_Store 36 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC := @gcc 2 | CXX := @g++ 3 | LIB_SRCS := $(shell find . -name "*.cpp") 4 | LIB_OBJS := $(LIB_SRCS:%.cpp=%.o) 5 | CPPLIB_WRAPPER = libcpplib_wrapper.so 6 | 7 | all: $(CPPLIB_WRAPPER) example_main 8 | 9 | $(CPPLIB_WRAPPER): $(LIB_OBJS) 10 | $(CXX) -shared -o $@ $^ 11 | 12 | # Could also use -fPIC, see http://stackoverflow.com/questions/3544035/what-is-the-difference-between-fpic-and-fpic-gcc-parameters 13 | ./%.o: ./%.cpp 14 | $(CXX) -fpic -c $< -o $@ 15 | 16 | example_main: 17 | $(CC) -L./ example_main.c -o example_main -lcpplib_wrapper 18 | 19 | # Remember to set LD_LIBRARY_PATH before running 'example_main', e.g.: 20 | # export LD_LIBRARY_PATH=/home/username/cpplib_wrapper:$LD_LIBRARY_PATH 21 | 22 | clean: 23 | rm -f *.o *.d $(CPPLIB_WRAPPER) example_main 24 | 25 | -include $(wildcard *.d) 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpplib_wrapper 2 | Example of how to create a plain C wrapper that calls C++ code. 3 | This is useful when working in a C-only environment and willing 4 | to use C++ code from a separate library. This repo provides an 5 | example of how to build the C++ code into a shared library and 6 | of how to write a C-only wrapper that calls and uses the C++ 7 | code. 8 | 9 | ## Overview 10 | * `cpp_class[.h|.cpp]` define a simple example C++ class with 11 | member functions that we want to call from C-only code. 12 | 13 | * `wrapper[.h|.cpp]` define a C-only interface that provides 14 | plain old functions that call the C++ code in `cpp_class`. 15 | 16 | * Both `cpp_class` and `wrapper` get compiled (using g++) into 17 | a shared library named `libcpplib_wrapper.so` by `Makefile`. 18 | 19 | * `example_main.c` is a C-only example program that is linked 20 | with `libcpplib_wrapper.so` and that can call the C++ code 21 | in `cpp_class` using the API provided by `wrapper`. 22 | 23 | * Running `make` using `Makefile` will generate the shared 24 | library `libcpplib_wrapper.so` and the binary `example_main`. 25 | 26 | ## Build and usage example 27 | Build in a UNIX environment by calling: 28 | ``` 29 | $ make 30 | ``` 31 | 32 | You should then see the following files in your directory: 33 | ``` 34 | $ ls 35 | cpp_class.cpp cpp_class.h cpp_class.o example_main example_main.c libcpplib_wrapper.so Makefile README.md wrapper.cpp wrapper.h wrapper.o 36 | ``` 37 | 38 | Update your `LD_LIBRARY_PATH` environment variable before running `example_main`: 39 | ``` 40 | $ export LD_LIBRARY_PATH=/home/user/.../cpplib_wrapper:$LD_LIBRARY_PATH 41 | ``` 42 | 43 | And now you can run the example program: 44 | ``` 45 | $ ./example_main 46 | Successfully using C++ object from C, pointer: 0x1cbc010 47 | 42 48 | ``` 49 | -------------------------------------------------------------------------------- /cpp_class.cpp: -------------------------------------------------------------------------------- 1 | #include "cpp_class.h" 2 | 3 | #include 4 | 5 | CppClass::CppClass(): 6 | a_(42) 7 | { 8 | 9 | } 10 | 11 | CppClass::~CppClass() 12 | { 13 | 14 | } 15 | 16 | void CppClass::do_work() 17 | { 18 | std::cout << this->a_ << std::endl; 19 | } 20 | -------------------------------------------------------------------------------- /cpp_class.h: -------------------------------------------------------------------------------- 1 | /** 2 | * cpp_class.h 3 | * 4 | * Declares a simple C++ class to be wrapped by a C API as an example. 5 | * 6 | */ 7 | 8 | #ifndef CPP_CLASS_H_ 9 | #define CPP_CLASS_H_ 10 | 11 | 12 | class CppClass { 13 | public: 14 | CppClass(); 15 | ~CppClass(); 16 | 17 | void do_work(); 18 | 19 | private: 20 | int a_; 21 | }; 22 | 23 | 24 | #endif /* CPP_CLASS_H_ */ 25 | -------------------------------------------------------------------------------- /example_main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This example program shows how to use a shared library (.so file) that 3 | * provides a C API for a C++ library. 4 | */ 5 | 6 | #include "wrapper.h" 7 | #include 8 | 9 | int main(int argc, char **argv) 10 | { 11 | CppClass *c = cpp_class_create(); 12 | printf("Successfully using C++ object from C, pointer: %p\n", (void*)c); 13 | cpp_class_do_work(c); 14 | cpp_class_destroy(c); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /wrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "wrapper.h" 2 | 3 | CppClass *cpp_class_create() 4 | { 5 | CppClass *c = new CppClass; 6 | return c; 7 | //return (void*)c; 8 | } 9 | 10 | void cpp_class_destroy(CppClass *c) 11 | { 12 | delete c; 13 | } 14 | 15 | void cpp_class_do_work(CppClass *c) 16 | { 17 | c->do_work(); 18 | } 19 | -------------------------------------------------------------------------------- /wrapper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * c_wrapper.h 3 | * 4 | * Declares a simple C API wrapper around a C++ class. 5 | * 6 | * This wrapper is compiled into a shared library (.so) 7 | * which can be then called from plain old C code. 8 | * 9 | * See an example program using this library in 10 | * applications/examples/cpplib_wrapper_example.c 11 | */ 12 | 13 | #ifndef C_WRAPPER_H_ 14 | #define C_WRAPPER_H_ 15 | 16 | 17 | #ifdef __cplusplus 18 | #include "cpp_class.h" 19 | extern "C" { 20 | #else 21 | typedef struct CppClass CppClass; 22 | #endif 23 | 24 | CppClass *cpp_class_create(); 25 | 26 | void cpp_class_destroy(CppClass *c); 27 | 28 | void cpp_class_do_work(CppClass *c); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | 35 | #endif /* C_WRAPPER_H_ */ 36 | --------------------------------------------------------------------------------