Created
May 27, 2011 18:28
-
-
Save kulp/162ce8447b4f739abaf0 to your computer and use it in GitHub Desktop.
Small cpp-based wrapper to provide C entry points for C++ libraries that don't need to be C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cshim.h" | |
#if CXX_VISIBLE | |
#define VISIBILITY extern "C" | |
#else | |
#define VISIBILITY static | |
#endif | |
#define CXX_SHIM(RetType,CxxFunc,Args,...) \ | |
VISIBILITY RetType CXX_NAME(CxxFunc) (CXX_OBJ c VA_ARGS(__VA_ARGS__)) \ | |
{ \ | |
return ((CXX_CLASS*)c->inner)->CxxFunc Args; \ | |
} | |
CXX_NAME(SHIM_LIST)(CXX_SHIM) | |
CXX_OBJ CXX_NAME(create)() | |
{ | |
CXX_OBJ me = new CXX_STRUCT_TAG(); | |
me->inner = new CXX_CLASS(); | |
#define CXX_ASSIGN(RetType,CxxFunc,Args,...) \ | |
me->CxxFunc = CXX_NAME(CxxFunc); | |
CXX_NAME(SHIM_LIST)(CXX_ASSIGN) | |
return me; | |
} | |
void CXX_NAME(destroy)(CXX_OBJ *what) | |
{ | |
delete (CXX_CLASS*)(*what)->inner; | |
delete *what; | |
*what = 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// types | |
#ifndef CSHIM_HH_ | |
#define CSHIM_HH_ | |
#ifndef CXX_PREFIX | |
#error "#define CXX_PREFIX to an identifier" | |
#endif | |
#ifndef CXX_CLASS | |
#error "#define CXX_CLASS to a class name" | |
#endif | |
#if defined(CXX_INCLUDE_C) | |
#include CXX_INCLUDE_C | |
#endif | |
#if defined(CXX_INCLUDE) && defined(__cplusplus) && !defined(MAKE_HUMAN_READABLE_CSHIM_H_) | |
#include CXX_INCLUDE | |
#endif | |
#define VA_ARGS(...) , ##__VA_ARGS__ | |
#define CAT3_(A,B,C) \ | |
A ## B ## C | |
#define CAT3(A,B,C) \ | |
CAT3_(A,B,C) | |
#define CXX_NAME(Stem) \ | |
CAT3(CXX_PREFIX,_,Stem) | |
#define CXX_OBJ \ | |
CXX_PREFIX | |
#define CXX_STRUCT_TAG \ | |
CXX_NAME() | |
// wraps preprocessor directives to hide them from first-level interpretation | |
#define EMIT(...) __VA_ARGS__ | |
#if __cplusplus && !defined(MAKE_HUMAN_READABLE_CSHIM_H_) | |
extern "C" { | |
#endif | |
// *_human.h is created from this file through a makefile rule. The _human file | |
// is the one intended to be included from a user program, since it is much more | |
// readable than this file. | |
#if MAKE_HUMAN_READABLE_CSHIM_H_ | |
EMIT(#ifndef CXX_NAME(CSHIM_H_)) | |
EMIT(#define CXX_NAME(CSHIM_H_)) | |
EMIT(#include CXX_INCLUDE_C) | |
#endif | |
typedef struct CXX_STRUCT_TAG *CXX_OBJ; | |
#if CXX_VISIBLE | |
#define CXX_FDEF(RetType,CxxFunc,Args,...) \ | |
RetType CxxFunc(CXX_OBJ me VA_ARGS(__VA_ARGS__)); | |
CXX_NAME(SHIM_LIST)(CXX_FDEF) | |
#endif | |
struct CXX_STRUCT_TAG { | |
void *inner; | |
#define CXX_DEF(RetType,CxxFunc,Args,...) \ | |
RetType (*CxxFunc)(CXX_OBJ me VA_ARGS(__VA_ARGS__)); | |
CXX_NAME(SHIM_LIST)(CXX_DEF) | |
}; | |
CXX_OBJ CXX_NAME(create)(void); | |
void CXX_NAME(destroy)(CXX_OBJ *what); | |
#if __cplusplus && !defined(MAKE_HUMAN_READABLE_CSHIM_H_) | |
}; | |
#endif | |
#if MAKE_HUMAN_READABLE_CSHIM_H_ | |
EMIT(#endif) | |
#endif | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CPPFLAGS += $(INCLUDE:%=-I%) $(DEFINES:%=-D%) | |
CXXFLAGS += -Wall -Wextra -Wno-unused | |
CC = gcc | |
LD = gcc | |
CFILES += $(wildcard *.c) | |
CXXFILES += $(wildcard *.cc) | |
CPP = g++ -x c++ -E -P | |
#DEFINES += CXX_VISIBLE=1 | |
CFLAGS += -g | |
CXXFLAGS += -g | |
CXXFLAGS += -O3 | |
#CXXFLAGS += -save-temps | |
CFLAGS += -save-temps | |
.DEFAULT_GOAL = all | |
all: $(TARGETS) libcshim_$(CXX_CLASS).so | |
CLEANFILES += $(TARGETS) | |
$(TARGETS): CFLAGS += -std=c99 | |
$(TARGETS): LDFLAGS += $(CXX_LDFLAGS) | |
$(TARGETS): LDLIBS += -lcshim_$(CXX_CLASS) $(CXX_LDLIBS) | |
$(TARGETS): | libcshim_$(CXX_CLASS).so | |
# TODO try to restruct the targets ? rename .so ? | |
DEFINES += 'CXX_PREFIX=$(CXX_PREFIX)' | |
DEFINES += 'CXX_CLASS=$(CXX_CLASS)' | |
DEFINES += 'CXX_INCLUDE="$(CXX_INCLUDE)"' | |
DEFINES += 'CXX_INCLUDE_C="$(CXX_INCLUDE_C)"' | |
DEFINES += 'CXX_INCLUDE_SHIM="$(CXX_INCLUDE_SHIM)"' | |
CLEANFILES += *_cshim.h # TODO unsafe | |
# requires make rules to check header dependencies, or to build cshim_human.h | |
# independently | |
$(CXX_CLASS)_cshim.h: cshim.h $(CXX_INCLUDE) | |
$(CPP) $(CPPFLAGS) -DMAKE_HUMAN_READABLE_CSHIM_H_ $< | indent > $@.$$$$ && mv $@.$$$$ $@ | |
cshim_$(CXX_CLASS),fPIC.o: CXXFLAGS += -fPIC | |
cshim_$(CXX_CLASS),fPIC.o: $(CXX_CLASS).cc | |
$(COMPILE.cc) -o $@ $^ | |
%,fPIC.o: CXXFLAGS += -fPIC | |
%,fPIC.o: %.cc | |
$(COMPILE.cc) -o $@ $^ | |
# TODO there are some dependencies missing on header files ; can get binary | |
# incompatibilities | |
CLEANFILES += cshim_$(CXX_CLASS),fPIC.o libcshim_$(CXX_CLASS).so | |
libcshim_$(CXX_CLASS).so: cshim,fPIC.o cshim_$(CXX_CLASS),fPIC.o | |
$(LINK.cc) -shared -o $@ $^ | |
clean: | |
$(RM) $(CLEANFILES) *.o *.ii *.i *.s | |
#CLEANFILES += *.d | |
#ifneq ($(MAKECMDGOALS),clean) | |
#-include $(CFILES:.c=.d) | |
#-include $(CXXFILES:.cc=.d) | |
#endif | |
# | |
#%.d: %.c | |
# @set -e; rm -f $@; \ | |
# $(CC) $(CPPFLAGS) -MM -MG -MF $@.$$$$ $<; \ | |
# sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | |
# rm -f $@.$$$$ | |
# | |
#%.d: %.cc | |
# @set -e; rm -f $@; \ | |
# $(CC) $(CPPFLAGS) -MM -MG -MF $@.$$$$ $<; \ | |
# sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | |
# rm -f $@.$$$$ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# the name of the class being wrapped | |
export CXX_CLASS = Test | |
# the prefix for C function names created | |
export CXX_PREFIX = TestWrap | |
# the C++ class declaration header | |
export CXX_INCLUDE = Test.h | |
# the header that contains the _SHIM decl | |
export CXX_INCLUDE_C = TestWrap.h | |
.PHONY: all clean | |
all: libcshim_Test.so | |
$(MAKECMDGOALS) clean: | |
$(MAKE) -f Makefile.cshim $@ | |
libcshim_Test.so Test_cshim.h: | |
$(MAKE) -f Makefile.cshim $@ | |
all: testuser | |
testuser: libcshim_Test.so | |
libcshim_Test.so: Test_cshim.h | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Test.h" | |
#include <iostream> | |
#include <cstdlib> | |
int Test::squawk(int a, char b) { | |
std::cout << "squawking " << a + b << std::endl; | |
return a + b; | |
} | |
void Test::die() { | |
abort(); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef TEST_H_ | |
#define TEST_H_ | |
class Test { | |
public: | |
int squawk(int a, char b); | |
void die(); | |
}; | |
#endif | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Test_cshim.h" | |
int main(void) | |
{ | |
TestWrap foo = TestWrap_create(); | |
foo->squawk(foo, 5, 4); | |
foo->die(foo); | |
TestWrap_destroy(&foo); | |
return 0; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define TestWrap_SHIM_LIST(_) \ | |
_(int,squawk,(a,b),int a, char b) \ | |
_(void,die,()) \ | |
// | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment