1

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.

  1. Why does it behave this way?
  2. Is there an option to put the actual code of method functions into separate source files and compile those individually?

1 Answer 1

1

If your function is static it is only visible in the cpp file where it is defined. You cannot call it from other cpp files (unless you first somehow has gotten a pointer to the function).

You have to remove static from the functions that are to be visible outside their own source file.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.