don_q
don_q

Reputation: 415

create a python module with C and Python code

I have a small python module I have created with the Python C API which I call mycore.

I have also created some utility scripts in Python which are related.

How can I put both in the same module namespace? I know I can call Python code from my C code but surely there is an easier way to do that.

Thanks

Upvotes: 3

Views: 264

Answers (2)

Jiminion
Jiminion

Reputation: 5168

OK, this worked for me. My circumstances may be different. My C module was built internally and provided to my embedded Python with a call to PyImport_AppendInittab().

But I still had some accompanying Python code that I wanted associated with the same namespace.

So I got it working by naming my C code _mygadget and the Python file mygadget.py. For the first line of mygadget.py I wrote:

from _mygadget import *

This seems to work. I don't know what would happen if I had a Python method and C call with the same name. I am avoiding that at present.

Upvotes: 0

user4815162342
user4815162342

Reputation: 155416

The obvious way is by making mycore a package. Create a mycore/__init__.py that imports both the C part, typically named something like _mycore, and the Python part:

from _mycore import *
from _mycorepy import *

In the same directory you'd have a _mycore.so and _mycorepy.py.

Another way to mix Python and C code is by invoking PyRun_String on the embedded Python. This might be what you mean by I know I can call Python code from my C code..., but just in case, here is a simple example with the potentially tricky refcounting details:

PyObject *get_factory()
{
  PyObject *g, *runret, *factory;
  // prepare a dictionary for the module to run in
  g = Py_BuildValue("{s:O}", "__builtins__", PyEval_GetBuiltins());
  if (!g)
    return NULL;
  // run Python code in the dictionary -- the code may import modules, etc.
  runret = PyRun_String("\
def factory():\n\
    return 42\n", Py_file_input, g, NULL);
  Py_XDECREF(runret);
  if (!runret) {
    Py_DECREF(g);
    return NULL;
  }
  Py_DECREF(runret);
  // pick the stuff you care about from the dictionary and return it
  factory = PyDict_GetItemString(g, "factory");
  Py_INCREF(factory);
  Py_DECREF(g);
  return factory;
}

Upvotes: 3

Related Questions