Skip to content

Instantly share code, notes, and snippets.

@physacco
Last active December 27, 2023 09:05
Show Gist options
  • Save physacco/2e1b52415f3a964ad2a542a99bebed8f to your computer and use it in GitHub Desktop.
Save physacco/2e1b52415f3a964ad2a542a99bebed8f to your computer and use it in GitHub Desktop.
Python 3 extension example
#include <stdio.h>
#include <Python.h>
// Module method definitions
static PyObject* hello_world(PyObject *self, PyObject *args) {
printf("Hello, world!\n");
Py_RETURN_NONE;
}
static PyObject* hello(PyObject *self, PyObject *args) {
const char* name;
if (!PyArg_ParseTuple(args, "s", &name)) {
return NULL;
}
printf("Hello, %s!\n", name);
Py_RETURN_NONE;
}
// Method definition object for this extension, these argumens mean:
// ml_name: The name of the method
// ml_meth: Function pointer to the method implementation
// ml_flags: Flags indicating special features of this method, such as
// accepting arguments, accepting keyword arguments, being a
// class method, or being a static method of a class.
// ml_doc: Contents of this method's docstring
static PyMethodDef hello_methods[] = {
{
"hello_world", hello_world, METH_NOARGS,
"Print 'hello world' from a method defined in a C extension."
},
{
"hello", hello, METH_VARARGS,
"Print 'hello xxx' from a method defined in a C extension."
},
{NULL, NULL, 0, NULL}
};
// Module definition
// The arguments of this structure tell Python what to call your extension,
// what it's methods are and where to look for it's method definitions
static struct PyModuleDef hello_definition = {
PyModuleDef_HEAD_INIT,
"hello",
"A Python module that prints 'hello world' from C code.",
-1,
hello_methods
};
// Module initialization
// Python calls this function when importing your extension. It is important
// that this function is named PyInit_[[your_module_name]] exactly, and matches
// the name keyword argument in setup.py's setup() call.
PyMODINIT_FUNC PyInit_hello(void) {
Py_Initialize();
return PyModule_Create(&hello_definition);
}
#!/usr/bin/env python3
# encoding: utf-8
from distutils.core import setup, Extension
hello_module = Extension('hello', sources = ['hello.c'])
setup(name='hello',
version='0.1.0',
description='Hello world module written in C',
ext_modules=[hello_module])
@mga010
Copy link

mga010 commented Jun 24, 2020

Maybe someone here can help me. I do not only want to create a module in C, I also want to use it in C. The following code, however, shows that my embedded method is not read.

#include <stdio.h>
#include <Python.h>

const char* pystart = 
"print('Start')\n\
import eumat\n\
print(dir(eumat))\n\
print(eumat.test())";

static PyObject* ftest (PyObject* self, PyObject* args)
{
	return PyLong_FromLong(1000);
}

static PyMethodDef EmbMethods[] = {
	{
		"test", (PyCFunction)ftest, METH_NOARGS,"Test Function"
	},
	{NULL, NULL, 0, NULL}
};

int main()
{
	printf("Test Programm for Python 3.8\n");

	Py_Initialize();

	static struct PyModuleDef moduledef = {
		PyModuleDef_HEAD_INIT,
		"eumat",
		PyDoc_STR("EMT Module"),
		-1,
		EmbMethods
	};

	PyObject* eumat = PyModule_Create(&moduledef);
	if (!eumat)
	{
		printf("Could not create eumat module in Python.");
		return 0;
	}

	PyObject* pModule = PyImport_AddModule("eumat"); //create main module
	if (!pModule)
	{
		printf("Could not add the module eumat in Python.");
		return 0;
	}

	if (PyRun_SimpleString(pystart) == -1)
	{
		printf("Could not run pystart.");
		return 0;
	}

	return 1;
}

/*
Test Programm for Python 3.8
Start
['__doc__', '__loader__', '__name__', '__package__', '__spec__']
Traceback (most recent call last):
  File "", line 4, in 
AttributeError: module 'eumat' has no attribute 'test'
Could not run pystart.
C:\Users\reneg\source\repos\HalloWorld\x64\Release\HalloWorld.exe (process 30676) exited with code 0.
Press any key to close this window . . .
*/

@mga010
Copy link

mga010 commented Jun 26, 2020

Just for the records, I solved it:

#include <stdio.h>
#include <Python.h>

const char* pystart = 
"print('Start')\n\
import eumat\n\
print(dir(eumat))\n\
print(eumat.test())";

static PyObject* ftest (PyObject* self, PyObject* args)
{
	return PyLong_FromLong(1000);
}

static PyMethodDef EmbMethods[] = {
	{
		"test", (PyCFunction)ftest, METH_NOARGS,"Test Function"
	},
	{NULL, NULL, 0, NULL}
};

int main()
{
	printf("Test Programm for Python 3.8\n");

	Py_Initialize();

	static struct PyModuleDef moduledef = {
		PyModuleDef_HEAD_INIT,
		"eumat",
		PyDoc_STR("EMT Module"),
		-1,
		EmbMethods
	};


	PyObject* eumat = PyImport_AddModule("eumat"); //create main module
	if (!eumat)
	{
		printf("Could not add the module eumat in Python.");
		return 0;
	}

	PyModule_AddFunctions(eumat, EmbMethods);

	if (PyRun_SimpleString(pystart) == -1)
	{
		printf("Could not run pystart.");
		return 0;
	}

	return 1;
}

@wahaha233333
Copy link

Thanks bro!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment