首先我们会使用PyMODINIT_FUNC 和PyMethodDef 进行创建c的扩展。
关于PyMethodDef可以的参数含义可以在官网查看
第一步
// 简单的say hello 函数
static PyObject* say_hello(PyObject* self, PyObject* args) {
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
// lambda 函数调用
void set_seed(int seed) {
printf("seed %d!\n", seed);
}
// PyMethodDef methods 函数
static void init_module(PyModuleDef* mdef, PyObject* m) {
mdef->m_doc = "Inner c++ core of test";
typedef PyObject* (*Myds)(PyObject*,PyObject**,int64_t,PyObject*);
static PyMethodDef methods[] = {
{"hello", (PyCFunction)say_hello, METH_VARARGS, NULL},
// lambda 函数
{ "lambda_hello",
(PyCFunction)(Myds)[](PyObject* self, PyObject** args, int64_t n, PyObject* kw) -> PyObject* {
try {
uint64_t arg_filled=0;
(void)arg_filled;
if (n+(kw?Py_SIZE(kw):0)<=1 && n+(kw?Py_SIZE(kw):0)>=1 && PyLong_CheckExact(args[0])) {
int arg0 = PyLong_AsLong(args[0]);
//!PyErr_Occurred();
if (kw) {
auto kw_n = Py_SIZE(kw);
for (int i=0; i<kw_n; i++) {
auto ko = PyTuple_GET_ITEM(kw, i);
auto vo = args[i+n];
auto ks = PyUnicode_AsUTF8(ko);
uint khash = leetcode::hash(ks);
if (khash == 16948695u) {
// hash match seed
CHECK((PyLong_CheckExact(vo)));
arg0 = PyLong_AsLong(vo);
arg_filled |= 1ull << 0;
continue;
}
LOGf << "Not a valid keyword:" << ks;
}
}
return GET_PY_NONE((set_seed(arg0)));
}
} catch (const std::exception& e) {
std::stringstream ss;
ss << "Wrong inputs arguments";
PyErr_Format(PyExc_RuntimeError,
"%s\n%s\nFailed reason:%s",
ss.str().c_str(),
R""(The function declarations are:
void lambda_hello(int seed)
)"",
e.what()
);
}
return nullptr;
},
METH_FASTCALL | METH_KEYWORDS,
R""(Document:
lambda_hello
Declaration:
void lambda_hello(int seed))""
},
{NULL, NULL, 0, NULL}
};
PyModule_AddFunctions(m, methods);
}
// 定义Extention的入口 PyMODINIT_FUNC
#define PYJF_MODULE_INIT(name) \
PyMODINIT_FUNC PyInit_##name() { \
PyObject *m; \
try { \
PyModuleDef *def = new PyModuleDef(); \
memset(def, 0, sizeof(PyModuleDef)); \
def->m_name = #name; \
def->m_doc = ""; \
def->m_size = -1; \
Py_INCREF(def); \
m = PyModule_Create(def); \
init_module(def, m); \
} catch(const std::exception& e) { \
PyErr_SetString(PyExc_RuntimeError, e.what()); \
return nullptr; \
} \
return m; \
}
// 声明
PYJF_MODULE_INIT(example_name)
详细的项目代码见github