使用c语言扩展python第二篇,接收不同类型的参数

xuxiaobo.c

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

int count_substrings(const char *str, const char *delim) {
    int count = 0;
    char *token = strtok((char *)str, delim); // 注意这里的强制类型转换
    while (token != NULL) {
        count++;
        token = strtok(NULL, delim); // 继续分割剩余的字符串
    }
    return count;
}

//定义打招呼函数
static PyObject* xuxiaobo_hello(PyObject* self, PyObject* args) {
    char *name;
    char *dest = malloc(1024);
    if (!PyArg_ParseTuple(args, "s", &name)) {
        return NULL;
    }

    /*
    strcpy(dest, "");
    strcat(dest, "hello, ");
    strcat(dest, name);
    strcat(dest, "!");
    */

    sprintf(dest, "你好, %s!", name);

    return Py_BuildValue("s", dest);
}

//定义计算平方函数
static PyObject* xuxiaobo_square(PyObject* self, PyObject* args) {
    int num;
    if (!PyArg_ParseTuple(args, "i", &num)) {
        return NULL;
    }
    return Py_BuildValue("i", num * num);
}

//定义计算立方函数
static PyObject* xuxiaobo_cube(PyObject* self, PyObject* args) {
    double num;
    if (!PyArg_ParseTuple(args, "d:xuxiaobo_cube", &num)) {
        return NULL;
    }
    return Py_BuildValue("d", num * num * num);
}

//定义解析url参数函数
static PyObject* xuxiaobo_parse_url(PyObject* self, PyObject* args) {
	char *params_str;
	char *delim = "=&,. ";
	PyObject* pDict = PyDict_New();

    if (!PyArg_ParseTuple(args, "s", &params_str)) {
        return NULL;
    }

	int i = 0;
    char *token = strtok(params_str, delim);
    while (token != NULL) {
    	char key[1024];
    	char value[1024];
		if(i%2 == 0){
			strcpy(key, token);
			//printf("debug key=>%s\n", key);
		} else{
			strcpy(value, token);
			//printf("debug value=>%s\n", value);
			PyDict_SetItemString(pDict, key, Py_BuildValue("s", value));
		}
		token = strtok(NULL, delim);
    	i++;
    }
	//printf("i=>%d\n", i);

    return pDict;
}

//定义字符串切分函数,返回list
static PyObject* xuxiaobo_split_str_list(PyObject* self, PyObject* args) {
	char *params_str;
	char *delim = "&,. ";
	PyObject* plist = PyList_New(0);

    if (!PyArg_ParseTuple(args, "s", &params_str)) {
        return NULL;
    }

    char *token = strtok(params_str, delim);
    while (token != NULL) {
		PyList_Append(plist, Py_BuildValue("s", token));
		token = strtok(NULL, delim);
    }

    return plist;
}

//定义字符串切分函数,返回tuple
static PyObject* xuxiaobo_split_str_tuple(PyObject* self, PyObject* args) {
	char *delim = "&,. ";
	char *params_str;
	char params_str_tmp[1024];

    if (!PyArg_ParseTuple(args, "s", &params_str)) {
        return NULL;
    }

    strcpy(params_str_tmp, params_str);
	int max = count_substrings(params_str_tmp, delim);
	PyObject* ptuple = PyTuple_New(max);

    int i = 0;
    char *token = strtok(params_str, delim);
    while (token != NULL && i < max) {
    	//printf("[%d]debug=>%s\n", i, token);
    	PyTuple_SetItem(ptuple, i, Py_BuildValue("s", token));
		token = strtok(NULL, delim);
		i++;
    }

    return ptuple;
}

//定义字符串切分函数,返回set
static PyObject* xuxiaobo_split_str_set(PyObject* self, PyObject* args) {
	char *delim = "&,. ";
	char *params_str;
	PyObject* pset = PySet_New(NULL);

    if (!PyArg_ParseTuple(args, "s", &params_str)) {
        return NULL;
    }

    int i = 0;
    char *token = strtok(params_str, delim);
    while (token != NULL) {
    	//printf("[%d]debug=>%s\n", i, token);
    	if(PySet_Add(pset, Py_BuildValue("s", token)) == -1){
    		Py_DECREF(pset);
    		return NULL;
    	}
		token = strtok(NULL, delim);
		i++;
    }

    return pset;
}

//定义季节检测函数,返回bool
static PyObject* xuxiaobo_is_season(PyObject* self, PyObject* args) {
	char *params_str;
	char params_str_tmp[1024];

    if (!PyArg_ParseTuple(args, "s", &params_str)) {
        return NULL;
    }

    strcpy(params_str_tmp, params_str);

    if(strcmp(params_str_tmp, "春") == 0 ||
       strcmp(params_str_tmp, "夏") == 0 ||
	   strcmp(params_str_tmp, "秋") == 0 ||
	   strcmp(params_str_tmp, "冬") == 0){
        return PyBool_FromLong(1);
    }

    return PyBool_FromLong(0);
}

//定义多个季节检测函数,返回bool组成的列表
static PyObject* xuxiaobo_is_season_multi_list(PyObject* self, PyObject* args) {
    PyObject* list;
    Py_ssize_t len;
    int i;
	char params_str_tmp[1024];
	PyObject* plist = PyList_New(0);
	const char *item_str;

    if (!PyArg_ParseTuple(args, "O", &list)) {
        return NULL;
    }
    len = PyList_Size(list);
    //printf("len=>%lld\n", len);

    for (i = 0; i < len; i++) {
    	PyObject* item = PyList_GetItem(list, i);
    	item_str = PyUnicode_AsUTF8(item);
        //printf("item_str=>%s\n", item_str);
        strcpy(params_str_tmp, item_str);

        if(strcmp(params_str_tmp, "春") == 0 ||
           strcmp(params_str_tmp, "夏") == 0 ||
    	   strcmp(params_str_tmp, "秋") == 0 ||
    	   strcmp(params_str_tmp, "冬") == 0){
        	PyList_Append(plist, PyBool_FromLong(1));
        } else{
        	PyList_Append(plist, PyBool_FromLong(0));
        }
    }

    return plist;
}

//定义多个季节检测函数,返回bool组成的tuple
static PyObject* xuxiaobo_is_season_multi_tuple(PyObject* self, PyObject* args) {
    PyObject* iptuple;
    Py_ssize_t len;
    int i;
	char params_str_tmp[1024];
	const char *item_str;

    if (!PyArg_ParseTuple(args, "O", &iptuple)) {
        return NULL;
    }
    len = PyTuple_Size(iptuple);
    PyObject* ptuple = PyTuple_New(len);
    //printf("len=>%lld\n", len);

    for (i = 0; i < len; i++) {
    	PyObject* item = PyTuple_GetItem(iptuple, i);
    	item_str = PyUnicode_AsUTF8(item);
        //printf("item_str=>%s\n", item_str);
        strcpy(params_str_tmp, item_str);

        if(strcmp(params_str_tmp, "春") == 0 ||
           strcmp(params_str_tmp, "夏") == 0 ||
    	   strcmp(params_str_tmp, "秋") == 0 ||
    	   strcmp(params_str_tmp, "冬") == 0){
        	PyTuple_SetItem(ptuple, i, PyBool_FromLong(1));
        } else{
        	PyTuple_SetItem(ptuple, i, PyBool_FromLong(0));
        }
    }

    return ptuple;
}

//定义多个季节检测函数,返回key=>val.bool组成的dict
static PyObject* xuxiaobo_is_season_multi_dict(PyObject* self, PyObject* args) {
    PyObject* list;
    Py_ssize_t len;
    int i;
	char params_str_tmp[1024];
	const char *item_str;
	PyObject* pDict = PyDict_New();

    if (!PyArg_ParseTuple(args, "O", &list)) {
        return NULL;
    }
    len = PyList_Size(list);
    //printf("len=>%lld\n", len);

    for (i = 0; i < len; i++) {
    	PyObject* item = PyList_GetItem(list, i);
    	item_str = PyUnicode_AsUTF8(item);
        //printf("item_str=>%s\n", item_str);
        strcpy(params_str_tmp, item_str);

        if(strcmp(params_str_tmp, "春") == 0 ||
           strcmp(params_str_tmp, "夏") == 0 ||
    	   strcmp(params_str_tmp, "秋") == 0 ||
    	   strcmp(params_str_tmp, "冬") == 0){
        	PyDict_SetItemString(pDict, item_str, PyBool_FromLong(1));
        } else{
        	PyDict_SetItemString(pDict, item_str, PyBool_FromLong(0));
        }
    }

    return pDict;
}

// 实现函数,接收字典参数并返回其内容打印字符串
static PyObject* xuxiaobo_print_dict(PyObject* self, PyObject* args, PyObject* kwargs) {
    PyObject *pdict;
    if (!PyArg_ParseTuple(args, "O:xuxiaobo_print_dict", &pdict)) {
        return NULL;
    }
    if (!PyDict_Check(pdict)) {
        PyErr_SetString(PyExc_TypeError, "xuxiaobo_print_dict() requires a dictionary");
        return NULL;
    }
    // 打印字典内容
    PyObject *key, *value;
    Py_ssize_t pos = 0;
    char result[8192] = {""};
    while (PyDict_Next(pdict, &pos, &key, &value)) {
    	const char *tmpkey1 = PyUnicode_AsUTF8(key);
    	const char *tmpvalue1 = PyUnicode_AsUTF8(value);

    	char tmpkey2[1024];
    	char tmpvalue2[1024];

    	strcpy(tmpkey2, tmpkey1);
    	strcpy(tmpvalue2, tmpvalue1);

    	char *tmpstr = malloc(1024);
    	sprintf(tmpstr, "%s => %s ", tmpkey2, tmpvalue2);
        //printf("%s\n", tmpstr);

        strcat(result, tmpstr);
        //printf("%s\n", result);
    }
    return Py_BuildValue("s", result);
}

static PyObject* xuxiaobo_set_to_list(PyObject *self, PyObject *args) {
    PyObject *py_set;
    if (!PyArg_ParseTuple(args, "O", &py_set)) {
        return NULL;
    }

    if (!PySet_Check(py_set)) {
        PyErr_SetString(PyExc_TypeError, "Expected a set");
        return NULL;
    }

    // 将set转换为list,便于在C中处理
    PyObject *py_list = PySequence_List(py_set);
    if (py_list == NULL) {
        return NULL;
    }

    // 返回list对象
    return py_list;
}

static PyObject* xuxiaobo_get_bool_param(PyObject* self, PyObject* arg) {
    if (!PyBool_Check(arg)) {
        PyErr_SetString(PyExc_TypeError, "Argument must be a boolean");
        return NULL;
    }
    int value = PyObject_IsTrue(arg);
    if (value == -1) {
        return NULL;
    }

    char result[8192] = {""};
    char *tmpstr = malloc(1024);
    sprintf(tmpstr, "收到布尔类型参数: %s", value ? "True" : "False");
    strcat(result, tmpstr);

    return Py_BuildValue("s", result);
}

static PyObject* xuxiaobo_get_multi_param(PyObject* self, PyObject* args, PyObject* kwargs) {
	static char* kwlist[] = {"name", "age", "weight", "kemus", NULL};
    const char* name;
    int age;
    double weight;
    PyObject *kemus;


    // 解析位置参数和关键字参数
    //PyArg_ParseTupleAndKeywords可以同时处理位置参数和关键字参数
    //s|id"表示第一个参数是必须的字符串,后面的两个参数是可选的,其中i代表整数,d代表浮点数。|表示后面的参数是可选的
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sidO", kwlist, &name, &age, &weight, &kemus)) {
        return NULL;
    }

    if (!PySet_Check(kemus)) {
        PyErr_SetString(PyExc_TypeError, "kemus argument must be a set");
        return NULL;
    }

    PyObject *iter = PyObject_GetIter(kemus);
    PyObject *item;
    char kemustr[8192] = {""};
    while ((item = PyIter_Next(iter)) != NULL) {
    	const char *tmpvalue = PyUnicode_AsUTF8(item);
    	strcat(kemustr, tmpvalue);
    	strcat(kemustr, ",");
    }

    // 使用参数
    char result[8192] = {""};
    char *tmpstr = malloc(1024);
    sprintf(tmpstr, "姓名: %s, 年龄: %d, 体重: %f, 考试科目: %s", name, age, weight, kemustr);
    strcat(result, tmpstr);

    return Py_BuildValue("s", result);
}

static PyMethodDef XuxiaoboMethods[] = {
	{"hello", xuxiaobo_hello, METH_VARARGS, NULL},
    {"square", xuxiaobo_square, METH_VARARGS, NULL},
	{"cube", xuxiaobo_cube, METH_VARARGS, NULL},
    {"parse_url",  xuxiaobo_parse_url, METH_VARARGS, NULL},
    {"split_str_list", xuxiaobo_split_str_list, METH_VARARGS, NULL},
    {"split_str_tuple", xuxiaobo_split_str_tuple, METH_VARARGS, NULL},
    {"split_str_set", xuxiaobo_split_str_set, METH_VARARGS, NULL},
    {"is_season", xuxiaobo_is_season, METH_VARARGS, NULL},
    {"is_season_multi_list", xuxiaobo_is_season_multi_list, METH_VARARGS, NULL},
    {"is_season_multi_tuple", xuxiaobo_is_season_multi_tuple, METH_VARARGS, NULL},
    {"is_season_multi_dict", xuxiaobo_is_season_multi_dict, METH_VARARGS, NULL},
    {"print_dict", xuxiaobo_print_dict, METH_VARARGS | METH_KEYWORDS, NULL},
    {"set_to_list", xuxiaobo_set_to_list, METH_VARARGS, NULL},
    {"get_bool_param", xuxiaobo_get_bool_param, METH_O, NULL},
    {"get_multi_param", xuxiaobo_get_multi_param, METH_VARARGS | METH_KEYWORDS, NULL},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef xuxiaobomodule = {
    PyModuleDef_HEAD_INIT,
    "xuxiaobo",
    NULL,
    -1,
	XuxiaoboMethods
};

PyMODINIT_FUNC PyInit_xuxiaobo(void) {
    return PyModule_Create(&xuxiaobomodule);
}

  

test.py

#coding=utf-8

from xuxiaobo import *
import json

input = "徐小波"
output = hello(input)
print("函数调用: %s hello('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = 3
output = square(input)
print("函数调用: %s square(%s)" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = 3.0
output = cube(input)
print("函数调用: %s cube(%s)" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = "a=1&b=2&c=3&d=我爱北京天安门"
output = parse_url(input)
print("函数调用: %s parse_url('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = "河.北.大.学.徐,小&波"
output = split_str_list(input)
print("函数调用: %s split_str_list('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = "河.北.大.学.徐,小.波& 啊"
output = split_str_tuple(input)
print("函数调用: %s split_str_tuple('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = "河.北.大 学.河.北.大 学 河.北 大&学"
output = split_str_set(input)
print("函数调用: %s split_str_set('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = "夏"
output = is_season(input)
print("函数调用: %s is_season('%s')" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = ["春", "夏", "秋", "东", "冬"]
output = is_season_multi_list(input)
print("函数调用: %s is_season_multi_list(%s)" % (type(input), json.dumps(input, ensure_ascii=False)))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = ("春", "下", "秋", "冬", "上")
output = is_season_multi_tuple(input)
print("函数调用: %s is_season_multi_tuple(%s)" % (type(input), json.dumps(input, ensure_ascii=False)))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = ["春", "下", "秋", "冬", "上"]
output = is_season_multi_dict(input)
print("函数调用: %s is_season_multi_dict(%s)" % (type(input), json.dumps(input, ensure_ascii=False)))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = {'下': '下邳', '秋': '秋天', '冬': '司机入伙', '上': '13110813222', '春三': '2222'}
output = print_dict(input)
print("函数调用: %s print_dict(%s)" % (type(input), json.dumps(input, ensure_ascii=False)))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = {'下', '秋', '冬', '上'}
output = set_to_list(input)
print("函数调用: %s set_to_list(%s)" % (type(input), input))
print("输出:%s %s" % (type(output), json.dumps(output, ensure_ascii=False)))
print()

input = False
output = get_bool_param(input)
print("函数调用: %s get_bool_param(%s)" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

input = ('徐香香', 15, 103.5, {'语文', '数学', '英语'})
output = get_multi_param(*input)
print("函数调用: %s get_multi_param(%s)" % (type(input), input))
print("输出:%s %s" % (type(output), output))
print()

  

测试输出:

函数调用: <class 'str'> hello('徐小波')
输出:<class 'str'> 你好, 徐小波!

函数调用: <class 'int'> square(3)
输出:<class 'int'> 9

函数调用: <class 'float'> cube(3.0)
输出:<class 'float'> 27.0

函数调用: <class 'str'> parse_url('a=1&b=2&c=3&d=我爱北京天安门')
输出:<class 'dict'> {"a": "1", "b": "2", "c": "3", "d": "我爱北京天安门"}

函数调用: <class 'str'> split_str_list('河.北.大.学.徐,小&波')
输出:<class 'list'> ["河", "北", "大", "学", "徐", "小", "波"]

函数调用: <class 'str'> split_str_tuple('河.北.大.学.徐,小.波& 啊')
输出:<class 'tuple'> ["河", "北", "大", "学", "徐", "小", "波", "啊"]

函数调用: <class 'str'> split_str_set('河.北.大 学.河.北.大 学 河.北 大&学')
输出:<class 'set'> {'河', '学', '大', '北'}

函数调用: <class 'str'> is_season('夏')
输出:<class 'bool'> True

函数调用: <class 'list'> is_season_multi_list(["春", "夏", "秋", "东", "冬"])
输出:<class 'list'> [true, true, true, false, true]

函数调用: <class 'tuple'> is_season_multi_tuple(["春", "下", "秋", "冬", "上"])
输出:<class 'tuple'> [true, false, true, true, false]

函数调用: <class 'list'> is_season_multi_dict(["春", "下", "秋", "冬", "上"])
输出:<class 'dict'> {"春": true, "下": false, "秋": true, "冬": true, "上": false}

函数调用: <class 'dict'> print_dict({"下": "下邳", "秋": "秋天", "冬": "司机入伙", "上": "13110813222", "春三": "2222"})
输出:<class 'str'> "下 => 下邳 秋 => 秋天 冬 => 司机入伙 上 => 13110813222 春三 => 2222 "

函数调用: <class 'set'> set_to_list({'秋', '下', '冬', '上'})
输出:<class 'list'> ["秋", "下", "冬", "上"]

函数调用: <class 'bool'> get_bool_param(False)
输出:<class 'str'> 收到布尔类型参数: False

函数调用: <class 'tuple'> get_multi_param(('徐香香', 15, 103.5, {'英语', '语文', '数学'}))
输出:<class 'str'> 姓名: 徐香香, 年龄: 15, 体重: 103.500000, 考试科目: 英语,语文,数学,

  

posted @ 2025-07-11 14:51  河北大学-徐小波  阅读(279)  评论(0)    收藏  举报