I have a c++ program which have a Tcl interpreter.
I wrap my functions and add them into Tcl interpreter manually.
Is it possible to wrap and add them by Swig automatically?
Here is the simplified code:
#include <stdio.h>
#include <tcl.h>
class SystemData { // I have a class which link to all the data and function
public:
void print(){
printf("Hello!\n");
};
};
// I wrap the functions manually. But I'm tired to maintain them.
int Hello( ClientData clientData, Tcl_Interp *interp, int argc, const char **argv ) {
SystemData* system = (SystemData*) clientData;
system->print();
}
int main (int argc, char *argv[]) {
Tcl_Interp *interp = Tcl_CreateInterp();;
SystemData* system = new SystemData;
Tcl_CreateCommand( interp, "hello", Hello, (ClientData)system, (Tcl_CmdDeleteProc *)NULL );
Tcl_Eval(interp, "hello"); // I have a Tcl interpreter so that I can call any function in any time
Tcl_DeleteInterp(interp);
}
I have tried to export SystemData to Tcl by Swig:
// swig.cc
#include <stdio.h>
#include <tcl.h>
class SystemData {
public:
void print(){
printf("Hello!\n");
};
};
SystemData* systemData;
int main (int argc, char *argv[]) {
Tcl_Interp *interp = Tcl_CreateInterp();;
systemData = new SystemData;
Tcl_Eval(interp, "load ./swig.so swig");
Tcl_Eval(interp, "puts $systemData");
Tcl_DeleteInterp(interp);
}
My Swig interface:
/* swig.i */
%module swig
%{
/* Put header files here or function declarations like below */
class SystemData;
extern SystemData* systemData;
%}
extern SystemData* systemData;
The compile commands:
swig -tcl swig.i
g++ -fpic -c swig.cc swig_wrap.c -I/usr/local/include
g++ -shared swig.o swig_wrap.o -o swig.so
However, the result of puts $systemData is
NULL
I also tried do not load swig.so
However, the result of puts $systemData is
can't read "systemData": no such variable
Anyone have an idea?
The problem is in the compile commands. My finally commands are:
swig -c++ -tcl swig.i
g++ -fpic -c swig.cc swig_wrap.cxx
g++ -shared swig.o swig_wrap.o -o swig.so
g++ swig.o swig_wrap.o -o swig.out -g -I/usr/local/include -L/usr/local/lib -ltcl8.5
setenv LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib
./swig.out
And the output of above commands are:
swig.i:22: Warning(454): Setting a pointer/reference variable may leak memory.
_906e600000000000_p_SystemData
Related
This question already has answers here:
Difference between -pthread and -lpthread while compiling
(3 answers)
Closed 4 years ago.
I want to make use of pthread ad hence use the -lpthread flag to compile, but here's what I get:
$ g++ -lpthread pseudo_code.cpp
/tmp/cc3mPrvt.o: In function `MyThreadClass::StartInternalThread()':
pseudo_code.cpp:(.text._ZN13MyThreadClass19StartInternalThreadEv[_ZN13MyThreadClass19StartInternalThreadEv]+0x26): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
The code I try to compile is below:
#include <pthread.h>
#include <iostream>
#include <vector>
#define OK 0
#define ERROR -1
//-- ThreadClass
class MyThreadClass
{
public:
MyThreadClass() {/* empty */}
virtual ~MyThreadClass() {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool StartInternalThread()
{
return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
}
/** Will not return until the internal thread has exited. */
void WaitForInternalThreadToExit()
{
(void) pthread_join(_thread, NULL);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void InternalThreadEntry() = 0;
private:
static void * InternalThreadEntryFunc(void * This) {
((MyThreadClass *)This)->InternalThreadEntry(); return NULL;
}
pthread_t _thread;
};
//-- /ThreadClass
//--- DUMMY DECLARATIONS BELOW TO MAKE IT COMPILE ---//
#define LOG_NS_ERROR std::cout
class test{
public:
int get_child(std::string x){return OK;};
};
test *_global;
typedef struct test_struct{} _db_transact;
class db_transact{
public:
db_transact(int,int&,int&){};
};
int _ns;
int _log_id;
//--- DUMMY DECLARATIONS ABOVE TO MAKE IT COMPILE ---//
class db_c_hndlr : public MyThreadClass{
public:
db_c_hndlr(void);
~db_c_hndlr(void);
db_transact *db_conn_get(void);
void InternalThreadEntry(void *func);
private:
int _stop;
std::vector<db_transact*> _db_pool;
};
//---------------------------------------------------------
db_c_hndlr::db_c_hndlr(void) {
}
//---------------------------------------------------------
void db_c_hndlr::InternatThreadEntry(void *func) {
while(!stop){
std::cout << "going!" << std::endl;
sleep(1);
}
}
//---------------------------------------------------------
db_c_hndlr::~db_c_hndlr() {
int i = 0;
std::vector<db_transact*>::iterator it;
for (i=0, it = _db_pool.begin();it!=_db_pool.end();it++, i++) {
if (_db_pool[i])
if (_db_pool[i]!=NULL)
delete _db_pool[i];
}
}
//---------------------------------------------------------
db_transact *db_c_hndlr::db_conn_get(void) {
db_transact *tmp;
tmp = new db_transact(_global->get_child("db_config"), _ns, _log_id);
_db_pool.push_back(tmp);
return tmp;
}
//---------------------------------------------------------
int main(void)
{
db_transact *conn=NULL;
db_c_hndlr db;
//db = new db_c_hndlr();
conn= db.db_conn_get();
return OK;
}
Probably you need to do this:
extern "C" {
#include <pthread.h>
}
That tells the compiler that this header is for a C library, and that it should not use C++ name mangling.
You also need to use -pthread instead of -lpthread, because the pthread library is special and GCC wants to explicitly know you are trying to use threads, not simply link against libpthread.
Please try to compile with the command.
g++ pseudo_code.cpp -lpthread
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, foo.o -lz bar.o searches library z after
file foo.o but before bar.o. If bar.o refers to functions in z, those
functions may not be loaded.
It worked for me. It seems, needs to specify the library after the source file so that symbols are searched in the library.
expr.hpp
typedef int (*evaluate)(PExp);
typedef void (*printTo)(PExp, FILE *);
typedef void (*Exp_free)(PExp);
class Expression {
public:
virtual int evaluate() abstract;
virtual void printTo(FILE * out) abstract;
virtual void free();
};
class Value : public Expression {
protected:
int value;
Value(int value);
public:
int evaluate();
};
Expression.h
#include <stdlib.h>
#include <stdio.h>
typedef struct expression Expression;
typedef Expression * PExp;
typedef int (*evaluate)(PExp);
typedef void (*printTo)(PExp, FILE *);
typedef void (*Exp_free)(PExp);
typedef struct {
evaluate exp_evaluate;
printTo exp_printTo;
Exp_free exp_free;
} vTable;
struct expression {
vTable * v;
};
void expression_init(PExp this);
void exp_free(PExp this);
Value.h
#include "Expression.h"
typedef struct {
Expression super;
int value;
} Value;
void value_init(Value * this, int value);
int value_evaluate(Value * this);
Constant.h
typedef struct {
Value super;
} Constant;
void constant_init(Constant * this, int value);
void constant_free(Constant * this);
void constant_printTo(Constant * this, FILE * out);
expr.h
#include "Expression.h"
#include "Value.h"
#include "Constant.h"
main.c
#include "expr.h"
void constant_init(Constant * this, int value) {
_ZN5ValueC2Ei((Value *)this, value);
printf("%d\n", this->super.super.v->exp_evaluate((PExp)this));
this->super.super.v->exp_printTo = (printTo)constant_printTo; // MARK
}
void constant_printTo(Constant * this, FILE * out) {
fprintf(out, "%d", this->super.value );
putchar('\n');
}
I'm currently trying to implement some code which constructs some objects in C while using C++ at the same time. The classes "Expression" and "Value" are given in C++ and I have to implement the class "Constant" which extends "Value" in C. I cannot change anything in the C++ files (including new files) so that's why I call the "Value" constructor by it's mangled name. The question is: I can call the method exp_evaluate which is defined in the class "Value" but when I try to override the method exp_printTo (MARKED line) it always gives me Segmentation Fault, so what am I doing wrong here?. If I try to call the method, instead of trying to assign another value to the function pointer, it terminates as expected because it is a pure virtual method. Here is the makefile showing that "main" is compiled with 3 C++ files and main.c:
main: use-expr.o expr.o main.o
g++ -o use-expr-c use-expr.o expr.o main.o -g
use-expr.o: use-expr.cpp expr.hpp
g++ -Wall -pedantic -g -c use-expr.cpp -g
expr.o: expr.cpp expr.hpp
g++ -Wall -pedantic -g -c expr.cpp -g
main.o: main.c
gcc -Wall -pedantic -std=c99 -g -c -o main.o main.c -g
It all compiles, the only error I get is at runtime.
I hope there's enough information.
Thank you in advance.
I'd suggest you implement a small wrapper (in C++) that calls the C++, and make the function there have C linkage using extern C. This is a far more reliable method than calling mangled C++ names.
If you really want to know what's up, I'm afraid it's time to break out gdb.
Using Eclpse on Linux I have defined a C++ class, named ABC (ABC.hpp):
#ifndef ABC_HPP_
#define ABC_HPP_
#include <stdio.h>
// namespace my { <---- COMMENTED OUT
class ABC {
private:
int m_number;
public:
ABC(int p_number);
void doSomething();
virtual ~ABC();
};
// } /* namespace my */ <---- COMMENTED OUT
#endif /* ABC_HPP_ */
and its implementation is (ABC.cpp):
#include "ABC.hpp"
// using namespace my; <---- COMMENTED OUT
ABC::ABC(int p_number) {
this->m_number = p_number;
}
ABC::~ABC() {
this->m_number = -1;
}
void ABC::doSomething() {
printf("doing something (%d)\n", this->m_number);
}
To use this class in C programs, I have created a layer containing these methods (ABCwrapper.h):
typedef void CABC;
#ifdef __cplusplus
extern "C" {
#endif
CABC* create_abc();
void call_abc_methods(const CABC *p_abc);
void destroy_abc(CABC *p_abc);
#ifdef __cplusplus
} // extern "C"
#endif
and
#include "ABC.hpp"
#include "ABCWrapper.h"
extern "C" {
CABC* create_abc() {
ABC* abc = new ABC();
return (ABC*)abc;
}
void call_abc_methods(const CABC *p_abc) {
ABC* abc = (ABC*)p_abc;
abc->doSomething();
}
void destroy_abc(CABC *p_abc) {
ABC* abc = (ABC*)p_abc;
delete abc;
}
}
That's fine and I can use the ABC class instance. But what about the define the ABC class in a name space, let's say "my"? If I remove the comment signs from all name space lines the IDE complains saying that the "Type 'ABC' could not be resolved".
If I want to extend my C++ library I have to use name space for my classes but then I don't know how to use in wrappers. Please, help me to solve this mystery.
Thank you.
SK
Some mostly minor nitpicks about the code. You've already got the details of the solution with an active namespace, but there are various minor issues that should be addressed.
You would be better off introducing an incomplete type, typedef struct CABC CABC; (in place of typedef void CABC;), so that you get some type safety in the C code. This would prevent you passing a random FILE *, for example, to the C interface functions, which using void won't.
When you use the incomplete type, you should use reinterpret_cast<ABC *>(abc) in the C wrapper functions instead of C-style casts. The compiler then shows up a problem with const-ness in the call_abc_methods() function; the argument should not be const (but the C-style cast hid the problem).
Additionally, your ABC.hpp header shows a common (minor) mistake; it includes an extraneous header (#include <stdio.h>) that is not needed to use the header safely. That line should only appear in the implementation file, ABC.cpp, where the code uses the services of <stdio.h>. Most headers should #include only those other headers necessary to make the header usable on its own. They should not include random other headers.
Here's a complete working program — which has a lot of files. There are 3 headers:
ABC.hpp — declaring class ABC.
ABCwrapper.h — declaring the C interface to class ABC.
ABCprogram.h — bilingual header declaring other functions.
There is 1 C file:
ABCuser.c — there must be some C code that needs to use the C interface to class ABC to make the whole exercise worthwhile, and this is it.
There are 3 C++ files:
ABC.cpp — defining class ABC.
ABCwrapper.cpp — defining the C interface to class ABC.
ABCmain.cpp — the main program in a bilingual system should normally be written in C++.
And there's a makefile.
ABC.hpp
#ifndef ABC_HPP_INCLUDED
#define ABC_HPP_INCLUDED
namespace abc_library {
class ABC {
private:
int m_number;
public:
ABC(int p_number);
void doSomething();
virtual ~ABC();
};
} /* namespace abc_library */
#endif /* ABC_HPP_INCLUDED */
ABCwrapper.h
#ifndef ABCWRAPPER_H_INCLUDED
#define ABCWRAPPER_H_INCLUDED
typedef struct CABC CABC; // Pointer to this ncomplete type used in C code
#ifdef __cplusplus
extern "C" {
#endif
CABC *create_abc(int val);
void call_abc_methods(CABC *p_abc);
void destroy_abc(CABC *p_abc);
#ifdef __cplusplus
}
#endif
#endif /* ABCWRAPPER_H_INCLUDED */
ABCprogram.h
#ifndef ABCPROGRAM_H_INCLUDED
#define ABCPROGRAM_H_INCLUDED
#if defined(__cplusplus)
extern "C" {
#endif
extern int c_code_function(int init);
#if defined(__cplusplus)
}
#endif
#endif /* ABCPROGRAM_H_INCLUDED */
ABCuser.c
#include "ABCwrapper.h"
#include "ABCprogram.h"
int c_code_function(int init)
{
CABC *abc = create_abc(init);
call_abc_methods(abc);
destroy_abc(abc);
return 0;
}
ABC.cpp
#include "ABC.hpp"
#include <stdio.h>
using namespace abc_library;
ABC::ABC(int p_number) {
this->m_number = p_number;
}
ABC::~ABC() {
this->m_number = -1;
}
void ABC::doSomething() {
printf("doing something (%d)\n", this->m_number);
}
ABCwrapper.cpp
#include "ABC.hpp"
#include "ABCwrapper.h"
using namespace abc_library;
extern "C" {
CABC *create_abc(int val) {
ABC* abc = new ABC(val);
return reinterpret_cast<CABC*>(abc);
}
void call_abc_methods(CABC *p_abc) {
ABC *abc = reinterpret_cast<ABC *>(p_abc);
abc->doSomething();
}
void destroy_abc(CABC *p_abc) {
ABC* abc = reinterpret_cast<ABC *>(p_abc);
delete abc;
}
}
ABCmain.cpp
#include "ABCprogram.h"
int main()
{
return c_code_function(39);
}
makefile
CC = gcc # /usr/bin/gcc
CXX = g++
RM_FR = rm -fr --
WFLAGS = -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition
SFLAGS = -std=c99
OFLAGS = -g -O3
UFLAGS = # Set on make command line only
OXXFLAGS = -g -O3
SXXFLAGS = -std=c++11
WXXFLAGS = -Wall -Wextra
UXXFLAGS = # Set on make command line only
LDFLAGS =
LDLIBS =
CFLAGS = ${OFLAGS} ${SFLAGS} ${WFLAGS} ${UFLAGS}
CXXFLAGS = ${OXXFLAGS} ${SXXFLAGS} ${WXXFLAGS} ${UXXFLAGS}
PROGRAM = abc
FILES.cpp = \
ABC.cpp \
ABCmain.cpp \
ABCwrapper.cpp
FILES.c = \
ABCuser.c
FILES.h = \
ABCprogram.h \
ABCwrapper.h
FILES.o = ${FILES.cpp:.cpp=.o} ${FILES.c:.c=.o}
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CXX} -o $# ${CXXFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}
clean:
${RM_FR} *.o *.dSYM core a.out
depend:
mkdep ${FILES.cpp} ${FILES.c}
# DO NOT DELETE THIS LINE or the blank line after it -- make depend uses them.
ABC.o: ABC.cpp
ABC.o: ABC.hpp
ABCmain.o: ABCmain.cpp
ABCmain.o: ABCprogram.h
ABCuser.o: ABCprogram.h
ABCuser.o: ABCuser.c
ABCuser.o: ABCwrapper.h
ABCwrapper.o: ABC.hpp
ABCwrapper.o: ABCwrapper.cpp
ABCwrapper.o: ABCwrapper.h
In ABCWrapper.cpp, above the extern "C" { line, add:
using my::ABC;
or
using namespace my;
john's suggestion (replace all instances of ABC with my::ABC in ABCWrapper.cpp) also works.
You have to set the scope for your ABC class. So replace all the ABC class as my::ABC except in the class declaration.
extern "C" {
CABC* create_abc() {
my::ABC* abc = new my::ABC();
return (my::ABC*)abc;
}
void call_abc_methods(const CABC *p_abc) {
my::ABC* abc = (my::ABC*)p_abc;
abc->doSomething();
}
void destroy_abc(CABC *p_abc) {
my::ABC* abc = (my::ABC*)p_abc;
delete abc;
}
}
This is the error I am keep getting . undefined reference to my class. I am not sure. I think I m linking them. this is how my main looks like.
#include <iostream>
#include "randomNumberMagnifier.h"
using namespace std;
int main()
{
randomNumberMagnifier r1, r2;
cout << "Random Number "<< r1.getRandomNumber();
cout << endl;
}
I am not sure what I am doing wrong.
this is what it looks like. when I compile
[singha1#cs1 p4]$ g++ -c randomNumberMagnifier.cpp
[singha1#cs1 p4]$ g++ -o p4Driver.cpp
g++: no input files
p4Driver.cpp:(.text+0x8c): undefined reference to `randomNumberMagnifier::getRandomNumber
collect2: ld returned 1 exit status
#ifndef RANDOMNUMBERMAGNIFIER_H
#define RANDOMNUMBERMAGNIFIER_H
class randomNumberMagnifier
{
int addFactor;
int multFactor;
bool addOn;
bool multOn;
int randomNumber;
static const int MAX_ADD_FACTOR = 100;
static const int MAX_MULT_FACTOR = 20;
static const int MAX_RANDOM = 200;
public:
randomNumberMagnifier();
//~randomNumberMagnifer();
randomNumberMagnifier& operator=(const randomNumberMagnifier& rhs);
randomNumberMagnifier(const randomNumberMagnifier& arandom);
randomNumberMagnifier(bool aState, bool mState);
int randomMagnifier();
int getAdd();
int getMult();
bool getAddState();
bool getMultState();
int getRandomNumber();
};
#endif
g++ -o p4Driver.cpp
That doesn't say what it's supposed to compile to, which is what -o is supposed to be for. You want:
g++ -c randomNumberMagnifier.cpp
g++ -c p4Driver.cpp
g++ randomNumberMagnifier.o p4Driver.o -o p4Driver
Or just:
g++ randomNumberMangifier.cpp p4Driver.cpp -o p4Driver
you need to provide randomNumberMagnifier.o to g++ command, so it can find function definition. I tested with below command and i worked
g++ -o p4Driver p4Driver.cpp randomNumberMagnifier.o
class Config
{
public:
static int OUTPUT_TO_FILE;
static int NEED_TO_TRAIN;
static int NO_FILE_TRAIN;
static int NEED_TO_TEST;
}
Above is my header.h file (i followed: http://weblogs.asp.net/whaggard/archive/2004/11/05/252685.aspx)
and I want to be able to do things like Config.OUTPUT_TO_FILE = true or variable = Config.NO_FILE_TRAIN;
from any file that includes config.h
I have what I want to do is clear, Just want some variable shared throughout all my cpp files.
EDIT:
I'm having trouble compiling:
In my make file, I added:
hPif : src/main.o src/fann_utils.o src/hashes.o src/config.o # added the config part
g++ src/main.o src/fann_utils.o src/hashes.o src/config.o -lfann -L/usr/local/lib -o hPif
config.o : src/config.cpp src/config.h
g++ -c src/config.cpp
.
.
.
main.o: src/main.cpp src/config.h src/main.h src/hashes.h
g++ -c src/main.cpp
config.cpp:
#include "config.h"
int OUTPUT_TO_FILE = false;
.
.
.
config.h:
class Config
{
public:
static int OUTPUT_TO_FILE;
.
.
.
Trying to call by:
#include "config.h"
...
Config::OUTPUT_TO_FILE = true;
Error I get:
Undefined Symbols:
"Config::OUTPUT_TO_FILE", referenced from:
_main in main.o
_main in main.o
Header (Config.h):
#pragma once
class Config
{
public:
static int OUTPUT_TO_FILE;
static int NEED_TO_TRAIN;
static int NO_FILE_TRAIN;
static int NEED_TO_TEST;
};
Source (Config.cpp):
#include "Config.h"
int Config::OUTPUT_TO_FILE = 0;
int Config::NEED_TO_TRAIN = 0;
int Config::NO_FILE_TRAIN = 0;
int Config::NEED_TO_TEST = 0;
Usage (any.cpp):
#include "Config.h"
...
int variable = Config::OUTPUT_TO_FILE;
...
In one of your source files, add something like this:
int Config::OUTPUT_TO_FILE = 1;
Now, it will be initialized on program startup. Only do this in one source .cpp file, not in multiple.
Because the class only has statics, you should be able to access them in any file which includes this header, for example..
foo.cpp
#include "Config.h"
void bar()
{
Config::NO_FILE_TRAIN = 0; // set this value for example
}
bar.cpp
#include "Config.h"
void foo()
{
Config::NEED_TO_TRAIN = 1; // set this value for example
}
Remember you must have an implementation file that is also compiled which actually defines the statics, i.e.
Config.cpp
int Config::OUTPUT_TO_FILE = 0; // initial value
: //etc.
You might want to implement your Config class as a singleton.
Oh, and if you want to set OUTPUT_TO_FILE = true, you'd be better off declaring OUTPUT_TO_FILE as bool...