I'm trying to use some C++ method in my python code and I'm using ctypes library. I have wrote a simple C++ code using a simple main with no arguments and another simple method named printArgs which takes an argument of type char *. I also have wrote a simple python code to import these two methods. I made two linked libraries(one .so and one .a because I'm using Debian) with this command:
g++ -o hello.so -shared -fPIC hello.cpp
And then used export LD_LIBRARY_PATH=/the/path/to/the/linked/libraries/directory.
There is no problem in getting the main method, bu when I'm trying to get printArgs I get AttributeError. Here's the C++ code:
#include <iostream>
using namespace std;
int printArgs(char * args_array){
for (int i = 0; i < 5; i++){
cout<<i<<"- "<<args_array[i]<<"\n";
}
return 0;
}
int main(){
cout<<"Hello\n";
return 0;
}
Here's the Python code:
from ctypes import *
helloInCPP_lib = cdll.LoadLibrary("hello.a")
print helloInCPP_lib
helloInCPPMain = helloInCPP_lib.main
print helloInCPPMain
helloInCPPPrint = helloInCPP_lib.printArgs
print helloInCPPPrint
I get this output:
<CDLL 'hello.a', handle 9c45488 at b73d1e6c>
<_FuncPtr object at 0xb73e67e4>
Traceback (most recent call last):
File "testHelloInCPP.py", line 9, in <module>
helloInCPPPrint = helloInCPP_lib.printArgs(None)
File "/usr/lib/python2.6/ctypes/__init__.py", line 366, in __getattr__
func = self.__getitem__(name)
File "/usr/lib/python2.6/ctypes/__init__.py", line 371, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /etc/linked_libraries/hello.a: undefined symbol: printArgs
I also tried cdll.LoadLibrary("hello.so") and/or helloInCPPPrint = helloInCPP_lib.printArgs(None); got the same error in both conditions. Any idea?
I'm using Debian 32 bit on a VMWare Workstation and Python 2.6.
Declare the printArgs using extern "C":
#include <iostream>
using namespace std;
extern "C" {
int printArgs(char * args_array);
}
int printArgs(char * args_array){
for (int i = 0; i < 5; i++){
cout<<i<<"- "<<args_array[i]<<"\n";
}
}
int main(){
cout<<"Hello\n";
}
BTW, you should pass a string (c_char_p), not None:
...
helloInCPPPrint = helloInCPP_lib.printArgs
helloInCPPPrint.argtypes = [c_char_p]
print helloInCPPPrint("ABCDE")
About argtypes, see Specifying the required argument types (function prototypes).
I tired compiling the solution by #falsetru using
g++ -O3 -shared -std=c++11 -fPIC code.cpp -o lib.so
but could not without this small modification to code.c, according to the link provided in their answer extern "C":
#include <iostream>
using namespace std;
extern "C" int printArgs(char * args_array){
for (int i = 0; i < 5; i++){
cout<<i<<"- "<<args_array[i]<<"\n";
}
}
Related
I'm trying to run MIT MEEP on ubuntu through its C++ lib but I've been widely unsuccessful. I have meep and g++ installed properly. I can run Scheme ctrl file but not the c++ libs.
I am trying the simple code from MEEP c++ tutorial. The meep.hpp is located where I have given. I am new to c++.
Could anyone give me a hint of what can be wrong?
These are the first lines of errors I get:
Building target: test2
Invoking: GCC C++ Linker
g++ -o "test2" ./src/test2.o
./src/test2.o: In function `main':
/home/mad/clipse_workspace/test2/Debug/../src/test2.cpp:20: undefined reference to `meep::initialize::initialize(int&, char**&)'
/home/mad/clipse_workspace/test2/Debug/../src/test2.cpp:22: undefined reference to `meep::vol2d(double, double, double)'
Here is the code I run:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include </usr/include/meep/meep.hpp>
using namespace meep;
using namespace std;
double eps(const vec &p);
int main(int argc, char **argv) {
initialize mpi(argc, argv); // do this even for non-MPI Meep
double resolution = 10; // pixels per distance
grid_volume v = vol2d(5,10, resolution); // 5x10 2d cell
structure s(v, eps, pml(1.0));
fields f(&s);
f.output_hdf5(Dielectric, v.surroundings());
double freq = 0.3, fwidth = 0.1;
gaussian_src_time src(freq, fwidth);
f.add_point_source(Ey, src, vec(1.1, 2.3));
while (f.time() < f.last_source_time()) {
f.step();
}
f.output_hdf5(Hz, v.surroundings());
return 0;
}
double eps(const vec &p) {
if (p.x() < 2 && p.y() < 3)
return 12.0;
return 1.0;
}
You have to link the MEEP library. I compiled your app like this:
g++ -o test2 test2.cpp -lmeep
MEEP development files can be installed like this on Ubuntu:
sudo apt-get install libmeep-dev
Also modify the include statement like this now:
#include <meep.hpp>
I tested this on Ubuntu 15.10 and your app worked fine.
Let's take a look at my project.
I'm using Visual Studio 2008, Python 2.7 and numpy 1.8.1 (but I have tried several versions and none worked). My project is being compiled on debug mode.
It's a very simple code:
/* = Main.cpp file = */
#include "stdafx.h"
#include "Python.h"
int _tmain(int argc, _TCHAR* argv[])
{
PyObject *pName, *main;
Py_Initialize();
pName = PyUnicode_FromString("main");
main = PyImport_Import(pName);
Py_XDECREF(pName);
if (main != NULL)
{
printf("Python Module Loaded!!\n");
}
else
{
printf("Unable to load Python Module!!\n");
}
return 0;
}
And
""" = Main.py file = """
print 'Hello World!'
If I execute this code, I get:
As it is expected.
My problem arises as soon as I change main.py into:
""" = Main.py file = """
import numpy
print 'Hello World!'
Then I get the:
I have tried to run main.py separately on a python interpreter (not embedding it into C++) and then everything works just fine:
I have also tried a modification on the main.cpp as follows:
#include "stdafx.h"
#include "Python.h"
int _tmain(int argc, _TCHAR* argv[])
{
PyObject *pName, *main;
Py_Initialize();
PyRun_SimpleString("import numpy");
return 0;
}
From this code the output is:
Finally I also tried compiling original version of main.cpp code in release mode and then the output is:
So, my question here is: What can I do to get numpy working under debug compilations using an embedded interpreter on Visual Studio 2008?
You know you have to have use a python debug version built don't you? That is probably your problem. (I would leave a comment but no rep ): )
I've been trying to learn spidermonkey and so have written the following code, adapted from this guide and while the program compiles properly, I get the following error during linking:
/usr/bin/ld: cannot open linker script file symverscript: No such file or directory
I'm using 64-bit Ubuntu 13.10, and here is the code (seems irrelevant to the problem, but can't hurt)
#include <jsapi.h>
#include <iostream>
#include <string>
int main()
{
std::string script = "var x = 10;x*x;";
jsval rval;
JSRuntime* runtime = 0;
JSContext* context = 0;
JSObject* globalob = 0;
if((!(runtime = JS_NewRuntime(1024L*1024L, JS_NO_HELPER_THREADS)))||
(!(context = JS_NewContext(runtime, 8192)))||
(!(globalob = JS_NewObject(context, NULL, NULL, NULL))))
{
return 1;
}
if(!JS_InitStandardClasses(context, globalob))
{
return 1;
}
if(!JS_EvaluateScript(context,globalob,script.data(),script.length(),"script",1,&rval))
{
return 1;
}
std::cout << JSVAL_TO_INT(rval) << "\n";
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
return 0;
}
compiled with the command
g++ main.cpp -o out $(js24-config --cflags --libs | tr "\n" " ")
Try to write this command instead,
g++ main.cpp -o main -I/usr/local/include/js/ -L/usr/local/lib/ -lmozjs1.8.5
regarding the path I wrote above, you must write your own path which include the library and JSAPI.h file included in,
And the last term is spidermonkey library, you will find it in lib folder, for me it exists in /usr/local/lib
I have some python code that I want to use from C++, I want to build it in lib or dll? how can I do it?
code have dependencies:
import socket
import string
import struct
import sys
and maybe PIL
You can use cython and write thin wrapper to export it to C
Cython lib helloWorld.pyx:
import sys
sys.path.append(".") #yourlib is in current folder
import yourlib #you can import any python module
cdef public void helloWorld():
print "Hello World Cython!"
yourlib.helloWorld("Python")
cdef public int my_sum(int x, int y):
return x*x+y
from libcpp.string cimport string
cdef public string testString( string sx, string sy ):
x = int(sx.c_str())
y = int(sy.c_str())
ret= "%d*%d+%d=%d"%(x,x,y,my_sum(x,y))
cdef char* ret2= ret
return string( ret2 )
Compile with cython (create helloWorld.cpp, helloWorld.h):
cython --cplus helloWorld.pyx
Your code program.cpp:
#include <string>
#include <iostream>
#include "Python.h"
#include "helloWorld.h" // it's cpp header so remove __PYX_EXTERN_C (bug)
int main(int argc, char *argv[]) {
Py_Initialize(); //start python interpreter
inithelloWorld(); //run module helloWorld
helloWorld();
std::cout << testString("6","6") << std::endl; #it's fast!
Py_Finalize();
return 0;
}
Compile and run:
g++ program.cpp helloWorld.cpp -I/usr/include/python2.7/ -lpython2.7
./a.out
Hello World Cython!
Hello World Python!
6*6+6=42
Another way is to use boost::python
Your code program.cpp:
#include <string>
#include <iostream>
#include <boost/python.hpp>
int main(int argc, char *argv[]) {
Py_Initialize();
boost::python::object sys = boost::python::import("sys");
sys.attr("path").attr("append")(".");
boost::python::object main_module = boost::python::import("yourlib");
main_module.attr("helloWorld")("boost_python");
boost::python::object ret= main_module.attr( "my_sum" )( 10, 10 );
std::cout << boost::python::extract<char const*>(ret) << std::endl;
Py_Finalize();
return 0;
}
Compile and run:
g++ program.cpp -I/usr/include/python2.7/ -lpython2.7 -lpython_boost
./a.out
Hello World boost_python!
10*10+10=110
You might want to check how to embed python in another application (http://docs.python.org/extending/embedding.html).
I trying to test using python ctypes with a small C++ program that uses Oracle OCCI to see if it's possible to use such a combination. It compiles to an .so library file ok but I am getting a nice linker error when I try to use it from Python, I think:
#include <string>
#include <iostream>
#include "occi.h"
using namespace std;
using namespace oracle::occi;
static string userName = "****";
static string passWord = "****";
static string connectString = "****";
class Account{
public:
bool updateAccount(){
bool updated = false;
try{
Environment *env = Environment::createEnvironment(Environment::DEFAULT);
Connection *conn = env->createConnection(userName,passWord,connectString);
Statement *stmt = conn->createStatement("select * from test");
ResultSet *rs = stmt->executeQuery();
while(rs->next()){
cout<<rs->getString(1)<<endl;
cout<<rs->getString(2)<<endl;
cout<<rs->getString(3)<<endl;
}
conn->terminateStatement(stmt);
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
}catch(...){
}
return updated;
}
};
extern "C" {
Account* Account_new(){ return new Account(); }
bool Account_updateAccount(Account* account){ account->updateAccount(); }
}
#!/usr/local/bin/python2.6
import ctypes
import os
lib = ctypes.cdll.LoadLibrary(os.getcwd()+'/occi.so')
class Account(object):
def __init__(self):
self.obj = lib.Account_new()
def updateAccount(self):
lib.Account_updateAccount(self.obj)
if __name__ == "__main__":
a = Account()
b = a.updateAccount()
print str(b)
Error when I run ctest.py:
Traceback (most recent call last):
File "./ctest.py", line 7, in <module>
lib = ctypes.cdll.LoadLibrary('/oracle/ctypes/occi.so')
File "/usr/local/lib/python2.6/ctypes/__init__.py", line 431, in LoadLibrary
return self._dlltype(name)
File "/usr/local/lib/python2.6/ctypes/__init__.py", line 353, in __init__
self._handle = _dlopen(self._name, mode)
OSError: ld.so.1: python2.6: fatal: relocation error: file /oracle/ctypes/occi.so: symbol _ZN6oracle4occi11Environment17createEnvironmentENS1_4ModeEPvPFS3_S3_jEPFS3_S3_S3_jEPFvS3_S3_E: referenced symbol not found
Any ideas, could it be an issue with using the Oracle Instant Client libs. I have seen weird issues with these in the past when trying to compile other 3rd party libraries against them ?
Thanks