返回字符串

 
void get_str(int i, char** tmp){
    sprintf(*tmp,"%d",i);
}

 
PyObject* ta_get_str(PyObject *self, PyObject *args, PyObject *kwargs) {
    char* tmp;
    int i;
    static char* keywords[] = { "i",NULL };
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", keywords, &i)) {
        return NULL;
    }

    get_str(i,&tmp);

    // Py_RETURN_NONE;
    return PyBytes_FromString(tmp);
}

 
import ta
res=ta.get_str(3)
res.decode('utf-8')
'3'
返回整数

 
PyObject *ta_system(PyObject *self, PyObject *args)
{
    const char *command;
    int sts;

    if (!PyArg_ParseTuple(args, "s", &command))
        return NULL;

    //system是C自带函数,不需要再自定义了
    sts = system(command);
    if (sts < 0) {
        PyErr_SetString(PyExc_ValueError, "System command failed");
        return NULL;
    }
    return PyLong_FromLong(sts);
}
    
返回空

 
void print_str(const char *s1,const char *s2){
    printf("%s,%s\n",s1,s2);
}

 
PyObject *ta_print_str(PyObject *self, PyObject *args, PyObject *kwargs) {
    /* Shared references that do not need Py_DECREF before returning. */
    PyObject *obj = NULL;
    int number = 0;
    char* s1;
    char* s2;

    /* Parse positional and keyword arguments */
    static char* keywords[] = { "s1", "s2", NULL };
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", keywords, &s1, &s2)) {
        return NULL;
    }
    /* Function implementation starts here */
    print_str(s1,s2);

    if (number < 0) {
        PyErr_SetObject(PyExc_ValueError, obj);
        return NULL;    /* return NULL indicates error */
    }

    Py_RETURN_NONE;
}

代码示例

ta.c

 
#include <stdio.h>
#include <stdlib.h> 

//-----------head.h start ---------------
#ifndef _TA_H_
#define _TA_H_

void print_str(const char *s1,const char *s2);

#endif
//-----------head.h end ---------------


//-----------ta.c start ---------------
void print_str(const char *s1,const char *s2){
    printf("%s,%s\n",s1,s2);
}
//-----------ta.c end ---------------


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

/*
    * Implements an example function.
    */
PyDoc_STRVAR(ta_print_str_doc, "print_str(ss) Example function");
PyDoc_STRVAR(ta_system_doc, "system(cmd) Example function");

PyObject *ta_print_str(PyObject *self, PyObject *args, PyObject *kwargs) {
    /* Shared references that do not need Py_DECREF before returning. */
    PyObject *obj = NULL;
    int number = 0;
    char* s1;
    char* s2;

    /* Parse positional and keyword arguments */
    static char* keywords[] = { "s1", "s2", NULL };
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", keywords, &s1, &s2)) {
        return NULL;
    }

    /* Function implementation starts here */
    print_str(s1,s2);


    if (number < 0) {
        PyErr_SetObject(PyExc_ValueError, obj);
        return NULL;    /* return NULL indicates error */
    }

    Py_RETURN_NONE;
}


PyObject *ta_system(PyObject *self, PyObject *args)
{
    const char *command;
    int sts;

    if (!PyArg_ParseTuple(args, "s", &command))
        return NULL;

    //system是C自带函数,不需要再自定义了
    sts = system(command);
    if (sts < 0) {
        PyErr_SetString(PyExc_ValueError, "System command failed");
        return NULL;
    }
    return PyLong_FromLong(sts);
}



/*
    * List of functions to add to ta in exec_ta().
    */
static PyMethodDef ta_functions[] = {
    { "print_str", (PyCFunction)ta_print_str, METH_VARARGS | METH_KEYWORDS, ta_print_str_doc },
    { "system", (PyCFunction)ta_system, METH_VARARGS | METH_KEYWORDS, ta_print_str_doc },
    { NULL, NULL, 0, NULL } /* marks end of array */
};


/*
    * Initialize ta. May be called multiple times, so avoid
    * using static state.
    */
int exec_ta(PyObject *module) {
    PyModule_AddFunctions(module, ta_functions);

    PyModule_AddStringConstant(module, "__author__", "tanpf");
    PyModule_AddStringConstant(module, "__version__", "1.0.0");
    PyModule_AddIntConstant(module, "year", 2023);

    return 0; /* success */
}

/*
    * Documentation for ta.
    */
PyDoc_STRVAR(ta_doc, "The ta module");


static PyModuleDef_Slot ta_slots[] = {
    { Py_mod_exec, exec_ta },
    { 0, NULL }
};

static PyModuleDef ta_def = {
    PyModuleDef_HEAD_INIT,
    "ta",
    ta_doc,
    0,              /* m_size */
    NULL,           /* m_methods */
    ta_slots,
    NULL,           /* m_traverse */
    NULL,           /* m_clear */
    NULL,           /* m_free */
};

PyMODINIT_FUNC PyInit_ta() {
    return PyModuleDef_Init(&ta_def);
}
        

setup_py38.py

 
from distutils.core import setup, Extension

setup(name='ta', version='1.0', \
ext_modules=[Extension('ta', ['ta.c'])])

编译安装

 
(base) [xt@ai1 python]$ cd ta/
(base) [xt@ai1 ta]$ ls
build  dist  setup_py38.py  ta.c  ta.egg-info
...
...
...
Installed /home/xt/anaconda3/lib/python3.9/site-packages/ta-1.0-py3.9-linux-x86_64.egg
Processing dependencies for ta==1.0
Finished processing dependencies for ta==1.0

调用

 
>>> import ta
>>> status = ta.system("pwd")
/opt/tpf/cwks/python/ta
>>> status
0
>>> ta.print_str('a','b')
a,b

编译安装

setup.py

 
from distutils.core import setup, Extension

setup(name='ta', version='1.2', \
ext_modules=[Extension('ta', ['ta.c'])])

编译安装

 
python setup.py install

几个注意事项

 
ta.c 是最全的文件,
C中可通过#include引用一堆文件,不必写这些引用的文件,只需要写上最全的文件即可

编辑安装不生效
明明修改了文件,但却没效果,可以尝试删除自动的build,dist目录,再次编辑

如果还不生效,就多改变一些C代码,比如增加一个方法等,
下次再不生效时,再把增加的这个无用方法注释掉,
大量的代码变动会迫使其重新编译 

参考文章
    Extending Python with C or C++
    pyobject的各种类型
    PyFloatObject
    PyTupleObject
    PyListObject
    c返回字符串