如何用python获取当前函数名解析获取C源文件的函数名

用C语言模仿Python函数的实例
投稿:jingxian
字体:[ ] 类型:转载 时间:
下面小编就为大家带来一篇用C语言模仿Python函数的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
首先得说明一点,C 语言不是函数式编程语言,要想进行完全的函数式编程,还得先写个虚拟机,然后再写个解释器才行(相当于 CPython )。
下面我们提供一个例子,说明 C 语言函数可以“适度地模仿” Python 函数。
我们有如下的 Python 程序:
def line_conf(a, b):
def line(x):
return a*x + b
return line
line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5), line2(5))
&我们在C程序中适度地模拟其中的line_conf函数:
/* MIT License
Copyright (c) 2017 Yuandong-Chen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
///////////////////////////////////////////////////////////////////////////////
// Note: The C program is almost equivalent to the Python program as follows:
// def line_conf(a, b):
def line(x):
return a*x + b
return line
// line1 = line_conf(1, 1)
// line2 = line_conf(4, 5)
// print(line1(5), line2(5))
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
#include &stdarg.h&
typedef int Func();
Func *line_conf(int x, int y,...)
va_start(ap, y);
asm volatile(
"push %%eax\n\t"
"subl $40, %%esp\n\t"
"movl 8(%%ebp), %%eax\n\t"
"movl %%eax, -36(%%ebp)\n\t"
"movl 12(%%ebp), %%eax\n\t"
"movl %%eax, -40(%%ebp)\n\t"
"addl $40, %%esp\n\t"
"pop %%eax\n\t"
:::"memory"
if(va_arg(ap,int) == 1){
asm volatile(
"push %%ebp\n\t"
"movl %%esp, %%ebp\n\t"
"movl 8(%%ebp), %%eax\n\t"
"imul -36(%%ebp), %%eax\n\t"
"addl -40(%%ebp), %%eax\n\t"
"movl %%ebp, %%esp\n\t"
"pop %%ebp\n\t"
:::"memory","%eax"
va_end(ap);
return (Func *)(&&LINE);
int main(int argc, const char *argv[]){
printf("====TEST START====\n");
printf("34*234+6 ?= %d\n",line_conf(34,6)(234));
printf("1*3+2 ?= %d; 324*65+3 ?= %d; 13*66+2 ?= %d\n",line_conf(1,2)(3),line_conf(324,3)(65),line_conf(13,2)(66));
int fd = line_conf(1,6)(4);
Func *fun = line_conf(3,3);
int a = 1; // Limited point
printf("3*3+3 ?= %d; 1*4+6 ?= %d\n",fun(3),fd);
printf("====TEST END====\n");
// Compile it by the following command:
// gcc -m32 -O0 -fno-stack-protector CFunctional.c; ./a.out
// The terminal output should looks like:
// ====TEST START====
// 34*234+6 ?= 7962
// 1*3+2 ?= 5; 324*65+3 ?= 2+2 ?= 860
// 3*3+3 ?= 12; 1*4+6 ?= 10
// ====TEST END====
//Note: The limitation happens between line 86 and line 88, we cannot insert any function here
// whose stack is larger than 40 bytes.(Why is 40? check the inline assembler language)
结果在MacOSX和Ubuntu上(i386)都能通过简单的测试。但是可以看到,仅仅是简单的模拟,我们也得用到大量(按比例)的汇编,可读性很差,而且模拟程度非常有限,代码长度也更长。相反,对于这类一般功能的函数,Python可以很容易地模拟C语言的函数,而且模拟程度很高。
以上这篇用C语言模仿Python函数的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具PYTHON调用C函数_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
PYTHON调用C函数
阅读已结束,如果下载本文需要使用5下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢Python利用ctypes实现C库函数调用 - zbility - 博客园
莫问前程。
ctypes 是强大的,使用它我们就能够调 用动态链接库中函数,同时创建各种复杂的 C 数据类型和底层操作函数。使得python也具备了底层内存操作的能力,再配合python本身强大的表达能力,这才知道为什么python是黑客必学的编程语言。
0x01 &ctypes使用
ctypes 提供了三种方法调用动态链接库:cdll(), windll(), 和 oledll()。
它们的不同之处就在 于,函数的调用方法和返回值。cdll() 加载的库,其导出的函数必须使用标准的 cdecl 调用约定。
windll()方法加载的库,其导出的函数必须使用 stdcall 调用约定(Win32API 的原生约 定)。
oledll()方法和 windll()类似,不过如果函数返回一个 HRESULT 错误代码,可以使用 COM 函数得到具体的错误信息。
0X02 &调用约定
调用约定专指函数的调用方法。其中包括,函数参数的传递方法,顺序(压入栈或 者传给寄存器),以及函数返回时,栈的平衡处理。
下面这两种约定是我们最常用到的: cdecl and stdcall。
cdecl 调用约定: 函数的参数从右往左依次压入栈内,函数的调用者, 在函数执行完成后,负责函数的平衡。这种约定常用于 x86 架构的 C 语言里。
python_rocks(reason_one,reason_two,reason_three);
In x86 Assembly
push reason_three
push reason_two
push reason_one
call python_rocks
从上面的汇编代码中,可以清晰的看出参数的传递顺序,最后一行,栈指针增加了 12 个字节(三个参数传递个函数,每个被压入栈的指针都占 4 个字节,共 12
个), 使得 函数调用之后的栈指针恢复到调用前的位置。
stdcall调用约定:参数传递的顺序也是从右到左,不过栈的平衡处理由函数 my_socks 自己完成,而不是调用者。&
int my_socks(color_onecolor_two,color_three);
In x86 Assembly
push color_three
push color_two
push color_one
最后一点,这两种调用方式的返回值都存储在 EAX 中。
0x03 使用方法
Windows下:
from ctypes import *
msvcrt = cdll.msvcrt
msg = "Hello world!\n"
msvcrt.printf("Testing: %s", msg)
from ctypes import *
libc = CDLL("libc.so.6")
msg = "Hello, world!\n"
libc.printf("Testing: %s", msg)
使用 Python 创建一个 C数据类型很简单,可以很容易的使用由C或者C++些的组件。 下面这张图很好的表示了映射关系。
0x04&定义结构和联合
barley_char[8];
In Python&
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
from ctypes import *
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
value = raw_input("Enter the amount of barley to put into the beer vat:")
my_barley = barley_amount(int(value))
print "Barley amount as a long: %ld" % my_barley.barley_long
print "Barley amount as an int: %d" % my_barley.barley_int
print "Barley amount as a char: %s" % my_barley.barley_char
输出结果:
Enter the amount of barley to put into the beer vat:66
Barley amount as a long: 66
Barley amount as an int: 66
Barley amount as a char: B
给联合赋一个值就能得到三种不同的表现方式。最后一个 barley_char 输出的结果是 B, 因为 66 刚好是 B 的 ASCII 码。barley_char 成员同时也是个数组,一个八个字符大小的数组。在 ctypes 中申请一个数组, 只要简单的将变量类型乘以想要申请的数量就可以了。详解python如何调用C/C++底层库与互相传值
投稿:daisy
字体:[ ] 类型:转载 时间:
Python作为一门脚本解释语言,本身又很好的结合C++,所以使用Python开发,在性能要求的地方调用C/C++底层库,这简直是神器。本文详细介绍了Python调用C/C++底层库,互相传值问题,下面一起来看看。
开发环境:
Centos 7 + Python 3.5.1 + Qt Creator(只是使用Qt Creator编译而已,并没有使用QT的任何库)
Python调用C/C++库,我现在能做到的有两种方式
1.extern “C” 导出(互相传值比较麻烦,不建议使用这种方式):
将C/C++库做成和平常一样的DLL和或者.so,比如:
#include &Python.h&
//.cpp文件
//C/C++ my.so 或者my.dll
enter "C" void printHello()
std::cout&&"Hello World"&&std::
import ctypes
from ctypes import *
loadso = ctypes.cdll.LoadLibrary
mylib = loadso("./my.so")
mylib.printHello()
&&&Hello world
代码解释:
my.so 有一个C导出函数 printHello()
import ctypes& : 导入官方的一个库,顾名思义和C有关
loadso = ctypes.cdll.LoadLibrary& : loadso 表示加载库用的函数
mylib = loadso(“./my.so”)  //或者loadso(“my.dll”)& 加载my.so库
mylib.printHello() : 调用库函数
上述代码能正常输出:Hello World,但是他们没有互相传值
Python和C++互相传值
#include &Python.h&
//.cpp文件
enter "C" int printHello(const char* str)
std::cout&&str&&std::
那么Python的问题就来了
str = create_string_buffer(b"Hello World")
#mylib.printHello("Hello World") 这里死活就是显示:H,*(str+4)才是'e',*(str+8) 是'l' 依次类推
print (mylib.printHello(str))
&&&Hello World
#由于对Python不是特别的熟悉 怎么也做不到显示C++返回的字符串, Python只能显示C++返回的字符串子能看到一个地址而已
2.Python扩展C/C++
不多说,直接上代码
//.h文件 本来这是C++连接Mysql 我只摘抄部分代#include &Python.h&
//.cpp文件
//传递多个参数 Python传过来的参数在args里面
PyObject* printfHello(PyObject* self,PyObject* args)
const char*
if (!PyArg_ParseTuple(args, "i|s", &i,&str))
//i 表示整形 s 表示字符串
return PyLong_FromLong(0);
print("%d,%s",i,str);
return Py_BuildValue("s","OK");
//向Python返回OK字符串
//映射 知道MFC的一看就懂
static PyMethodDef MyMethods[] = {
{"printfHello", printfHello, METH_VARARGS,
//"printHello" 中可调用的函数 METH_VARARGS :带有参数
METH_NOARGS:无参数
{"connect", connect, METH_VARARGS,
"connect mysql"},
{NULL, NULL, 0, NULL}
static PyObject* UtilE
// 向Python中注册模块
static struct PyModuleDef spammodule = {
PyModuleDef_HEAD_INIT,
"libMysqlUtil", //模块名字 import libMysqlUtil
"C++ Connect Mysql",
};//PyInit_libMysqlUtil 注意名字 一定要PyInit_ 加上你的模块名字 不然Python import 会提示没有定义 PyInit_你的模块名字 PyMODINIT_FUNC PyInit_libMysqlUtil(void) { PyObject* m = m = PyModule_Create(&spammodule);
//m= Py_InitModule(....) Python 2.7 if(!m) { } UtilError = PyErr_NewException("Util.error",NULL,NULL); Py_INCREF(UtilError); PyModule_AddObject(m,"error",UtilError); }
import libMysqlUtil
libMysqlUtil.printHello(1,"hello World")
&&&1,hello World
到目前为止Python和C/C++互相通信,能适应大部分需求,结构体传值还没有研究,对于类,使用指针就行,C++里面是指针,在Python中会将指针转化成整形,Python将这个整形传给C++的时候使用PyArg_ParseTuple又将整形会变成类指针。
好了,以上就是本文的全部内容,希望本文的内容对大家学习python和C/C++能有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具如何用python解析获取C源文件的函数名?(或者有没有第三方的库) - 知乎2被浏览94分享邀请回答还没有回答

我要回帖

更多关于 python获取当前函数名 的文章

 

随机推荐