I've been following some code examples on how to build a C module for Python, however it seems like Py_InitModule isn't defined anywhere.
Most sources say it's within the modsupport.h file, but the macro isn't defined there.
I'm using the includes given by the Win32 binaries download, and everything seems in check.
Any suggestions?
Works for me on 2.7.2, Python 2 or 3? For example, for a module called Example:
Python 2:
/* Module entry point Python 2 */
PyMODINIT_FUNC initExample(void)
{
(void) Py_InitModule("Example", ExampleMethods);
}
Python 3:
/* Module entry point Python 3 */
PyMODINIT_FUNC PyInit_Example(void)
{
return PyModule_Create(&Example_module);
}
Related
I have a requirement where I need to embed Ruby code in C++ (I could achieve this) and extend some functionality. When I try to call (require) my extension module, the program fails.
I have pasted a jist of the code below:
main.cpp
#include <ruby.h>
static VALUE Sum(VALUE rb_self, VALUE rb_param1, VALUE rb_param2)
{
double val1 = NUM2DBL(rb_param1);
double val2 = NUM2DBL(rb_param2);
return rb_float_new(val1+val2);
}
void Init_myMod()
{
myMod = rb_define_module("myMod");
rb_define_module_function(myMod, "Sum", Sum, 2);
}
int main()
{
... Init ruby method...
rb_require("myRubyfile");
Init_myMod(); // This is where I need to push my ruby extension.
rb_funcall(rb_mKernel, rb_intern("helloworld"), 0 , NULL);
....
}
myRubyfile.rb
require "myMod"
def helloworld()
puts "Hello world"
#puts "Sum of.. " + myMod.sum(4, 5)
end
The problem is if I dont use require "myMod" the code works and prints "Hello World", but if I use require.., the code dumps.
This is my requirement where I need to embed the ruby script in C, and reuse some of the C methods in ruby (extension).
Can someone help me with this?
You're getting a segfault because the Ruby VM segfaults when there is an uncaught exception. You need to use something like rb_rescue or rb_protect to wrap the code which could raise an exception.
require "myMod" is raising an exception because require is only used to load files. You don't need to require anything because you're creating the module directly in the VM's memory. So... why the error? Well, if you were to write your module in Ruby, you'd get a syntax error:
module myMod
...
end
# SyntaxError: class/module name must be CONSTANT
But when you use rb_define_module, rather than raise an exception, Ruby does a tricky thing: it creates the module but doesn't expose it to the Ruby code. In order to expose the module to Ruby, just make the name valid:
// .cpp
rb_define_module("MyMod");
and
# .rb
puts "Sum of.. " + MyMod.Sum(4, 5).to_s
Something like this should work. Make a bat script to your ruby script file and change system to the appropriate system call. Not sure if system() works in Windows. I have run many bash scripts this way so I would assume you can do the same thing in Windows.
#include <stdio.h>
#include <stdlib.h>
int main()
{
puts("Starting now:");
system("/path_to_script/script_name");
return 0;
}
We have a DLL that implements a custom programming language. What I want to do is adding support for the python language keeping the same code for "API function".
I have succefully embedded python in this DLL, now I'm approaching the problem to expose all the old function as a python module.
Now this DLL doesn't expose the API function as interface function but it's installed (as function pointer) to the language engine. In this way it's impossible to create a new python module (a new DLL). But I need to keep the compatibility with the old method...
It's possible to create (and install) at runtime a module defined in the same DLL where the Python is located?
I think something like calling the PyInit_xxxx method after PyInitialize();
This has gotten substantially more complicated in Python 3 (vs. how it was in Python 2), but I've gotten it working for my code, so I hope this works for you as well.
// Python 3's init function must return the module's PyObject* made
// with PyModule_Create()
PyObject* initspam();
const char* spam_module_name;
int main(int argc, char **argv)
{
Py_Initialize();
PyImport_AddModule(spam_module_name);
PyObject* module = initspam();
PyObject* sys_modules = PyImport_GetModuleDict();
PyDict_SetItemString(sys_modules, spam_module_name, module);
Py_DECREF(module)
...
}
I found an example of this in the python 3 source code:
Python-3.4.2\Python\pythonrun.c : import_init()
That has much better error checking and such than my example above.
I've solved using a code like this before Py_Initialize();
/* Add a built-in module, before Py_Initialize */
PyImport_AppendInittab("xxx", PyInit_xxx);
The easiest way to handle this is to statically initialize your statically-linked modules by directly calling initspam() after the call to Py_Initialize() or PyMac_Initialize():
int main(int argc, char **argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initspam();
An example may be found in the file Demo/embed/demo.c in the Python source distribution.
I'm basically attempting to do the same as the following question but i'm getting run time errors at the call to PyObject_Print complaining about an error in "toupper() at 0x776e0226"
Python C API: Using PyEval_EvalCode
My code is:
int callExecFunction(const char* evalStr)
{
PyCodeObject* code = (PyCodeObject*)Py_CompileString(evalStr, "pyscript", Py_eval_input);
PyObject* global_dict = PyModule_GetDict(pModule);
PyObject* local_dict = PyDict_New();
PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);
PyObject* result = PyObject_Str(obj);
PyObject_Print(result, stdout, 0);
}
evalStr is "setCurrentFileDir()" and pModule was initialized earlier from a script without error and was working as this code: http://docs.python.org/2/extending/embedding.html#pure-embedding.
And inside the loaded module there is the function:
def setCurrentFileDir():
print "setCurrentFileDir"
return "5"
What have I missed/done wrong in the eval function call. Note that I cannot call the function setCurrentFileDir "directly" through the python API, I must use eval.
Actually this works fine. However I had a .pyd file in the directory that python must have built (and eclipse was hiding from me) from an older run of the python script that didn't have the function defined, causing the problem.
Here is where I got the idea that the problem maybe a .pyd file.
python NameError: name '<anything>' is not defined (but it is!)
I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.
I have implemented a class in C++. I want to use it with Python.
Please suggest step by step method and elaborate each step.
Somthing like this...
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
Now, in Python
>>> T1 = Test(12)
>>> T1.getInt()
12
>>> T1.setInt(32)
>>> T1.getInt()
32
Please suggest.How can I do this ?
NOTE: I would like to know manual way to do that. I don't want any third party library dependency.
Look into Boost.Python. It's a library to write python modules with C++.
Also look into SWIG which can also handle modules for other scripting languages. I've used it in the past to write modules for my class and use them within python. Works great.
You can do it manually by using the Python/C API, writing the interface yourself. It's pretty lowlevel, but you will gain a lot of additional knowledge of how Python works behind the scene (And you will need it when you use SWIG anyway).
ctypes is good. It is really easy to use, and it comes standard with Python. Unfortunately it can only talk to shared libraries (Unix) or DLLs (Windows) that have a C-style interface, which means you can't directly interface to a C++ object. But you could use a handle system where a handle refers to a particular object.
>>> getInt(h)
12
I think that is simple, easy to understand, and doesn't require extra libraries.
I would suggest you try SWIG or sip (KDE/PyQt).
SWIG link : http://www.swig.org/
SIP link: http://freshmeat.net/projects/python-sip/
These can be used to wrap C++ classes and provide a Pythonic interface to them.
This is a very old post, and probably the OP already found a solution to his problem, but since no one has yet provided a valid example, I will give it a try and maybe help someone like me with the same problem in hand.
Since the OP did not specify, I will restrict my answer to Windows, although a Linux solution would be straightforward. I will try to provide a minimal working example that reproduces the code in question.
Step 1) Start with the C++ code (a single file)
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
extern "C"
{
// include below each method you want to make visible outside
__declspec(dllexport) Test* init(int k) {return new Test(k);}
__declspec(dllexport) void setInt(Test *self, int k) {self->setInt(k);}
__declspec(dllexport) int getInt(Test *self) {return self->getInt();}
// Note: the '__declspec(dllexport)' is only necessary in Windows
}
Step 2) Compile the DLL shared library. E.g. from your working directory:
g++ -shared mytest.cpp -o libtest.dll
Step 3) Create the Python file with the wrapper:
# mytest.py
import ctypes
import platform
# From Python 3.8 onwards, there is a reported bug in CDLL.__init__()
mode = dict(winmode=0) if platform.python_version() >= '3.8' else dict()
lib = ctypes.CDLL('./libtest.dll', **mode)
class Test(object):
def __init__(self, val: int):
# Declare input and output types for each method you intend to use
lib.init.argtypes = [ctypes.c_int]
lib.init.restype = ctypes.c_void_p
lib.setInt.argtypes = [ctypes.c_void_p, ctypes.c_int]
lib.setInt.restype = ctypes.c_void_p
lib.getInt.argtypes = [ctypes.c_void_p]
lib.getInt.restype = ctypes.c_int
self.obj = lib.init(val)
def setInt(self, n):
lib.setInt(self.obj, n)
def getInt(self):
return lib.getInt(self.obj)
T1 = Test(12)
print(T1.getInt())
T1.setInt(32)
print(T1.getInt())
Step 4) Run the code
Below are my results when I run the script with 4 different Python versions:
PS D:\Desktop\mytest> py -3.7 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.8 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.9 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.10 .\mytest.py
Traceback (most recent call last):
File "D:\Desktop\mytest\mytest.py", line 7, in <module>
lib = ctypes.CDLL('./libtest.dll', **mode)
File "D:\Python\3102\lib\ctypes\__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'D:\Desktop\mytest\libtest.dll' (or one of its dependencies). Try using the full path with constructor syntax.
In the last case, I have tried with the full path and still same error.
I'm running on Windows 10 64bit and compiling with g++ 8.1.0 from MinGW64
Comments:
My answer is based in the solutions provided here, here, and here
A common problem arises when the Python and compiler (g++) architectures does not match (i.e. 32 or 64 bit)