I am using the Intel Pin tool to generate a shared object file from a C source file and a C++ pintool. I have used the following g++ commands to generate my shared object file. Apologies in advance as the commands are very big due to the Pin libraries and options.
g++ -DBIGARRAY_MULTIPLIER=1 -Wall -Werror -Wno-unknown-pragmas -D__PIN__=1 -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/gen -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/stlport/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/libstdc++/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/arch-x86_64 -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/components/include -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/include/xed -Iinc -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/tools/InstLib -O0 -c -o obj-intel64/testcpp.o testcpp.cpp
g++ -DBIGARRAY_MULTIPLIER=1 -Wall -Werror -Wno-unknown-pragmas -D__PIN__=1 -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/gen -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/stlport/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/libstdc++/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/arch-x86_64 -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/components/include -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/include/xed -Iinc -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/tools/InstLib -O0 -c -o obj-intel64/test.o test.c
g++ -shared -Wl,-z,defs -Wl,--hash-style=sysv /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt/crtbeginS.o -Wl,-Bsymbolic -Wl,--version-script=/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/pintool.ver -fabi-version=2 obj-intel64/testcpp.so -o obj-intel64/testcpp.o obj-intel64/test.o -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/lib -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/lib-ext -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/lib -lpin -lxed /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt/crtendS.o -lpin3dwarf -ldl-dynamic -nostdlib -lstlport-dynamic -lm-dynamic -lc-dynamic -lunwind-dynamic
testcpp.cpp is my C++ pintool and test.c is my C source file. The folder inc contains the header file test.h which is included in both of them.
This is my C++ file -
#include "pin.H"
#include <iostream>
#include <fstream>
extern "C" {
#include <test.h>
}
using namespace std;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI");
FILE * op;
VOID Instruction(INS ins, void *v) {
}
VOID Fini(INT32 code, VOID *v) {
fprintf(op,"Ended from c++\n");
fprintf(op,"%d\n",cfunc(11,2));
fclose(op);
}
INT32 Usage() {
PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char *argv[]) {
if (PIN_Init(argc, argv))
return Usage();
op = fopen("test.out", "w");
PIN_InitSymbols();
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
PIN_StartProgram();
return 0;
}
This is my C file-
#include <stdio.h>
#include <test.h>
int cfunc(int a, int b)
{
return(a+b);
}
void cfunc2()
{
printf("Hello from C %d\n",cfunc(3,5));
}
This is my test.h file-
int cfunc(int, int);
void cfunc2(void);
The rest of the options are pin specific and I simply used them from the sample programs and feel that they don't need modifications (I hope so!)
However when I generate my shared object file I get this error-
obj-intel64/testcpp.o: In function `Fini(int, void*)':
testcpp.cpp:(.text+0x41): undefined reference to `cfunc2'
collect2: error: ld returned 1 exit status
cfunc2 is the function I am trying to call. I do not understand where I am going wrong. I am including the right options and arguments, but somehow this symbol is undefined. Any suggestions?
You use g++ to compile the test.c file. The g++ compiler driver invokes the C++ compiler for .c files, so your functions will have C++ linkage, not C linkage. There are several ways to address thos:
Compile test.c with gcc instead of g++.
Drop the extern "C" from the C++ source file, so that C++ linkage is used everywhere.
Put the extern "C" into the header file, so that applies to the definition in test.c, too.
Related
I need to access a C++ function from C but I get some error like :-
/tmp/ccUqcSZT.o: In function `main':
main.c:(.text+0x5): undefined reference to `load_alert_to_db'
collect2: error: ld returned 1 exit status
My main.c code is:-
#include <stdio.h>
extern void load_alert_to_db(void);
int main(void){
/* Create empty queue */
load_alert_to_db();
return 0;
}
C++ code implementation db_manager.cpp is:-
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <time.h>
#include <cstring>
#include <fstream>
//using namespace oracle::occi;
#include <iostream>
using namespace std;
extern "C" void load_alert_to_db(void)
{
cout<<"db occi"<<endl;
}
makefile is:-
CC= g++
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
clean:
rm -f *.o data
so please help me which one is my problem. I am also include
export LD_LIBRARY_PATH=/home/oracle/Desktop/storage/:$LD_LIBRARY_PATH
environmental variable in .bash_profile
gcc -o data main.c
Not sure why you have this line in your makefile since it will compile main.c without reference to the previously created library and hence cause an undefined-symbol error such as the one you're seeing.
This is especially so, since you appear to have done it the right way on the preceding line:
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
However, the entire point of using makefiles is so that it figures out the minimum necessary commands for you, based on dependencies. Lumping a large swathe of commands into a single rule tends to defeat that purpose. You would be better off making your rules a little more targeted, such as (untested but should be close):
all: data
data: main.o libdb_manager.so
gcc -o data main.o -ldb_manager
main.o: main.c
gcc -o main.o main.c
libdb_manager.so: db_manager.cpp
g++ -c -Wall -Werror -fPIC -o db_manager.o db_manager.cpp
g++ -shared -o libdb_manager.so db_manager.o
That way, if you make a small change to one part (like main.c), it doesn't have to go and compile/link everything in your build tree.
Your makefile seems to be completely broken and random, and you're not even linking the required object files. You can simplify this:
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
to just this:
all:
gcc -Wall -c main.c
g++ -Wall -c db_manager.cpp
g++ main.o db_manager.o -o data
this is what I needed to do:
Supposing the C++ function is called Debug::Write(str)
Then in your hpp file do the following:
#ifdef __cplusplus
extern "C" void DebugTmp(char *str);
#endif
Then in the corresponding cpp file do this:
void DebugTmp(char *str)
{
Debug::Write(str);
}
Then in your C file where you call DebugTmp define the prototype:
void DebugTmp(char *str);
then call it as below:
static void MyFunction( void )
{
DebugTmp("This is debug trace\n");
}
I don't understand why RubyInline is crashing.
class CPPCode
inline do |builder|
builder.include '<algorithm>'
builder.include '<vector>'
builder.c 'int test(){return 1;}'
end
end
The error:
error executing "gcc -shared -fPIC -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -fPIC -L. -fstack-protector -rdynamic -Wl,-export-dynamic -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include/ruby-2.3.0 -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include/ruby-2.3.0/x86_64-linux -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include -L/home/lionzxy/.rvm/rubies/ruby-2.3.0/lib -o \"/home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.so\" \"/home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c\" ": pid 24454 exit 1 Renamed /home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c to /home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c.bad
Generated C++ file:
#include "ruby.h"
#include <algorithm>
#include <vector>
# line 58 "/home/lionzxy/RubymineProjects/app/models/book.rb"
static VALUE test(VALUE self) {
return INT2FIX(1);}
#ifdef __cplusplus
extern "C" {
#endif
void Init_Inline_Book__CPPCode_098f6bcd4621d373cade4e832627b4f6() {
VALUE c = rb_cObject;
c = rb_const_get(c, rb_intern("Book"));
c = rb_const_get(c, rb_intern("CPPCode"));
rb_define_method(c, "test", (VALUE(*)(ANYARGS))test, 0);
}
#ifdef __cplusplus
}
#endif
You're trying to use C++ code, but you're running gcc without any flags to tell it that it's C++ code.
On the first documentation page we see an example on how to use C++ code:
require 'inline'
class MyTest
inline(:C) do |builder|
builder.include '<iostream>'
builder.add_compile_flags '-x c++', '-lstdc++'
builder.c '
void hello(int i) {
while (i-- > 0) {
std::cout << "hello" << std::endl;
}
}'
end
end
t = MyTest.new()
t.hello(3)
The "trick" here is:
builder.add_compile_flags '-x c++', '-lstdc++'
which tells gcc that this is C++ code.
I have an existing application that uses a C++ class, a C++ wrapper, and FORTRAN code for the computationally intensive parts of the application. I would like to implement parts of the FORTRAN in CUDA to take advantage of parallelization, but I would still like to access some of the subroutines, so I need to link CUDA, C++, and FORTRAN code.
I have three questions:
1. How do I correctly link all of the object files with the Linux Terminal and with the Makefile (included below)?
2. What is the proper way to reference the CUDA function in the class header without confusing the compiler's recognition of device and host code?
3. Is passing a class to CUDA just like passing a class to any other external C code?
Note: I have not included full code (some of it is quite long) except for the Makefile. If I need to include more, please let me know.
.h file
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
//Want "advance" to be implemented in CUDA
}
/* Proper prototype of CUDA call? */
//extern "C" void cudaadvance(float *2Darray);
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C wrapper
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
main.C file
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
Makefile (Note: "pbo" is the FORTRAN code)
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $# $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $# $^ -L ../../amj/lib -lamjMemory -lg2c -lz
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
You currently don't have any CUDA code, so I may can't give enough details.
For your Qs:
Linking object files including CUDA code requires nvcc compiler driver. You could first compile your code files with individual compilers, i.e. gcc for .c, g++ for .cpp, g77 for .f and nvcc for .cu. Then you can use nvcc to link all the object files .o;
host and device code are explicitly declared in .cu file with __host__ and __device__. It's your responsibility not to invoke device code from other host code;
Why are your passing a class to CUDA? If you want to replace your fortran code with CUDA, you only need to invoke CUDA functions in your C++ wrapper class, and invoking CUDA API functions uses the the same grammar as invoking c++ functions.
Here is an example from my project. The executable is built with 1 .cu, 1 .cpp, a few extern .a as well as some .so. For .cpp I use Intel's compiler icpc other than the default g++. Please note my main() is in the .cu file.
# Compile : bin.cu/b-rbm-gpu.cu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -gencode arch=compute_20,code=sm_20 -Ilib -c -o bin.cu/b-rbm-gpu.o bin.cu/b-rbm-gpu.cu
# Compile : lib/KTiming.cpp
icpc -Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237 -O3 -MMD -Ilib -c -o lib/KTiming.o lib/KTiming.cpp
# Link : bin.cu/b-rbm-gpu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -Ilib -Llib bin.cu/b-rbm-gpu.o lib/KTiming.o -lpthread -lm /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_lp64.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_thread.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a -lcublas -lcurand -lcusparse -o bin.cu/b-rbm-gpu
Here is the solution. To use the CUDA code, I reference it with, for example,
extern "C" void myfunction_(void)
In the header file, I add
void myfunction_(void);
in the extern "C" prototypes. In the public functions of the class I added
void mycudafunction(void);
In the C++ wrapper, I add
void DGCPM::mycudafunction(){
myfunction_();
}
I can now call "myfunction" from the main program with this type of syntax
model = new class DGCPM();
model->mycudafunction();
I modified my Makefile by adding myfunction.o to all of my objects and adding
-L /usr/local/cuda/lib -lcuda -lcudart
to all of my linking instructions.
To compile, create the CUDA object file (myfunction.o), and link, I type this in the terminal:
nvcc -c myfunction.cu
make
Here is the modified code:
.h file
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
/*CUDA prototype, can be changed to "cudaadvance" or the like*/
void myfunction_(void);
}
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
void mycudafunction(void);
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C Wrapper
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
void DGCPM::mycudafunction(){
myfunction_();
}
main.C file
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->mycudafunction();
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
Makefile
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o myfunction.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o myfunction.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $# $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $# $^ -L ../../amj/lib -lamjMemory -lg2c -lz -L /usr/local/cuda/lib -lcuda -lcudart
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
Here's the simple CUDA program I used to test.
#include <stdio.h>
__global__ void kernel( void ) {
}
extern "C" void myfunction_(void) {
kernel<<<1,1>>>();
printf( "Hello, World!\n" );
return;
}
I am trying to create a baremetal c++ application for a cortex-M4 device. My toolchain is ARM-GCC
I have noticed that the code size has shot up by 300kb which is 30% of the available flash size. There is a whole truckload of stuff from the standard libraries that gets linked in bloating TEXT, DATA and BSS areas.
Can this be reduced?
The application is the venerable blinky program with a :
- Blinky.c containing the C routine to toggle a port pin in a while loop
- Main.cpp containing the main() and a simple class with a constructor
- Device startup file which does program loading and yields control to main()
The c file is compiled using gcc while the cpp is compiled using g++. The linker is invoked via g++ to automatically link in stdlibc++(with the assumption that only necessary object fies from the stdlibc++ will be linked in).
I even have -fno-rtti and -fno-exceptions as compile options to g++, but the savings are a pittiance.
By the way, the generated binary works file.
This is the Main.cpp
#include <iostream>
using namespace std;
extern "C" void Toggle_Pin(uint8_t Speed);
void *__dso_handle = (void *)NULL;
void __cxa_atexit(void (*Arg)(void *), void *Arg2, void *Arg3){}
void __cxa_guard_acquire(void){}
void __cxa_guard_release(void){}
void __aeabi_atexit(void (*Arg)(void *), void *Arg2, void *Arg3){}
class Computer
{
public:
uint32_t aa;
uint32_t bb;
Computer();
};
Computer::Computer()
{
aa=0;
bb=0;
for(uint8_t i=0;i < 10; i++)
{
Toggle_Pin((uint8_t)100);
}
}
Computer a;
int main(void)
{
a.aa = 10;
Toggle_Pin();
}
And these are my compilation options provided to g++.
-O0 -ffunction-sections -Wall -fno-rtti -fno-exceptions -mfloat-abi=softfp -Wa,-adhlns="$#.lst" -c -fmessage-length=0 -mfpu=fpv4-sp-d16 -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d) $#" -mcpu=cortex-m4 -mthumb -g3 -gdwarf-2 -o "$#" "$<"
Linker options provided to g++:
-T LinkerScript.ld" -nostartfiles -L"Path to libraries" -Wl,-Map,"Project.map" -mcpu=cortex-m4 -mthumb -g3 -gdwarf-2 -o "Project.elf" "#makefile.rsp" $(USER_OBJS) $(LIBS)
Remove part with
#include <iostream>
using namespace std;
you don't need it. I guess it adds extra global objects / variables and might leave some definitions in binary.
Also use -Os
-Os
Optimize for size. -Os enables all -O2 optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size.
example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Math {
public:
int pi() const;
void pi(int pi);
private:
int _pi;
};
#endif
example.cpp:
#include "example.h"
int Math::pi() const {
return this->_pi;
}
void Math::pi(int pi) {
this->_pi = pi;
}
example.swig:
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "example.h"
I then generate the wrappers, "example.py" and "example_wrap.c" using:
swig -python example.swig
When I try to compile the wrapper class using:
g++ -fPIC -c example.cpp example_wrap.c -I/usr/local/include/python2.6/
I get the following error:
example_wrap.cpp: In function "PyObject* Swig_var_Math_get()":
example_wrap.cpp:2725: error: expected primary-expression before "void"
example_wrap.cpp:2725: error: expected ")" before "void"
The Error is at the following line :
pyobj = SWIG_NewPointerObj(SWIG_as_voidptr(&Math), SWIGTYPE_p_class, 0 );
#define SWIG_as_voidptr(a) (void *)((const void *)(a))
Is it the right way to generate the wrapper class "example_wrap.c"?
I think the swig command should be "swig -c++ -python example.swig"
There's not enough information here to be sure what's wrong, but I have two ideas for things you can try.
Your g++ invocation is compiling a C source file as if it were C++. This is not guaranteed to work. Try instead
gcc -I/usr/local/include/python2.6 -fPIC -c example_wrap.c
gcc -I/usr/local/include/python2.6 -fPIC -c example.cpp
g++ -shared example_wrap.o example.o -o example.so
(yes, srsly, only use g++ for the link)
If that doesn't work, compile example_wrap.c like this:
gcc -I/usr/local/include/python2.6 -fPIC -c -save-temps example_wrap.c
That will fail the same way but will produce a file named example_wrap.i which is the result of preprocesing. It will be gigantic. Search that file for the function Swig_var_Math_get, and add to your question the complete text of that function (but nothing else).
Thanks for your replay!
The -C++ option generated the C++ class for the wrapper.
swig -c++ -v -python example.swig
I used g++ to compile the wrapper.
g++ -fPIC -c example.cpp example_wrap.cxx -I/usr/local/include/python2.6/
And the following command to buikd the shared object. Ofcourse, we need to remove the superflous includes (-I) and libraries (-L). The important flags are '-shared' and '-fPIC'.
g++ example_wrap.o example.o -L/u01/app/oracle/product/1020.full/lib -I/usr/local/ssl/include -L/usr/local/ssl/lib -lclntsh -lssl -lcrypto -ldl -L/usr/local/lib -L/lib64 -L/usr/local/lib/python2.6/ -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -lglog -lmodpbase64 -lpthread -ldl -lrt -shared -fPIC -o _example.so