I am trying to extend python with some c++ code. I have been sticking to the guide here
https://docs.python.org/2/extending/extending.html
I use the standard header spammodule.h
#ifndef Py_SPAMMODULE_H
#define Py_SPAMMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Header file for spammodule */
/* C API functions */
#define PySpam_System_NUM 0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)
/* Total number of C API pointers */
#define PySpam_API_pointers 1
#ifdef SPAM_MODULE
/* This section is used when compiling spammodule.c */
static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;
#else
/* This section is used in modules that use spammodule's API */
static void **PySpam_API;
#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
/* Return -1 on error, 0 on success.
* PyCapsule_Import will set an exception if there's an error.
*/
static int
import_spam(void)
{
PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
return (PySpam_API != NULL) ? 0 : -1;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* !defined(Py_SPAMMODULE_H) */
the actual function is put into a spam.cpp file
#define SPAM_MODULE
#include "spammodule.h"
#include <Python.h>
#include <iostream>
static PyObject * some_other_method(PyObject *self, PyObject *args);
static PyObject * spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
system(command);
sts = 2;
return Py_BuildValue("i", sts);
}
static int
PySpam_System(const char *command)
{
return system(command);
}
static PyMethodDef SpamMethods[] = {
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
{"some_other_method", some_other_method, METH_VARARGS, "do new stuff"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
In a file method.cpp I put
#include <Python.h>
#include <iostream>
static PyObject * some_other_method(PyObject *self, PyObject *args){
std::cout<<"hello world\n"<<std::endl;
int sts = 2;
return Py_BuildValue("i", sts);
}
This compiles with a warning:
spam.cpp:7:19: warning: ‘PyObject* some_other_method(PyObject*, PyObject*)’ used but never defined [enabled by default]
static PyObject * some_other_method(PyObject *self, PyObject *args);
and fails when importing in a python script.
import spam
spam.system("ls -l")
spam.some_other_method()
However, if I supplant the forward declaration of some_other_method with the actual code
//static PyObject * some_other_method(PyObject *self, PyObject *args);
#include "method.cpp"
it works fine.
- Why does it behave this way?
- Is there an option to put the actual code of method functions into separate source files and compile those individually?