动态链接库
如何将c文件转换成DLL文件并在python中调用? 首先得把c中需要在外部调用的函数调用约定限制为__cdecl,然后把c编译为动态库,Linux下用gcc编译器,windows下用msvc或者mingw64的gcc都可以。Python代码中使用ctype加载动态库就可以调用了。具体两三句话说不清楚。 本帖最后由 阿奇_o 于 2022-10-20 18:19 编辑我看你骨骼惊奇,直接给你以下秘籍:《C草巨蟒之DLL神掌》。。 能修炼到什么程度,就看你造化了,哈哈哈{:10_250:}
from ctypes import *
#----------以下四种加载DLL方式皆可—————————
# pDLL = WinDLL("./myTest.dll")
# pDll = windll.LoadLibrary("./myTest.dll")
# pDll = cdll.LoadLibrary("./myTest.dll")
pDll = CDLL("./TestDLL.dll")# 注意写全路径或相对路径
# 旧的cpp的例子:
# https://www.cnblogs.com/FHC1994/p/11421229.html
#调用动态链接库函数
# res = pDll.sum(1,2)# 旧的cpp加法的例子,返回 a+b
#打印返回结果
# print(res)
# 新例子(用gcc如何将c生成dll):
# https://www.bilibili.com/video/BV1E4411z7Ua/?vd_source=691572ece9556ac42935a92fe9cf7e76
# https://www.codementor.io/@a_hathon/building-and-using-dlls-in-c-d7rrd4caz
# msg = pDll.message()
# print(msg) # 这样会多出两个11 (异常?)
pDll.message()# 这样即可,因为它本身就是用C的printf()打印到stdout $ ls
main.c
$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
void and_gate(char a, char b, char *c) {
*c = a == '1' && b == '1' ? '1' : '0';
}
void or_gate(char a, char b, char *c) {
*c = a == '0' && b == '0' ? '0' : '1';
}
#if 0
void xor_gate(char a, char b, char *c) {
*c = a != b ? '1' : '0';
}
#else
void not_gate(char a, char *b) {
*b = a == '1' ? '0' : '1';
}
void xor_gate(char a, char b, char *c) {
char na, nb;
char r0, r1;
not_gate(a, &na);
not_gate(b, &nb);
and_gate(a, nb, &r0);
and_gate(b, na, &r1);
or_gate(r0, r1, c);
}
#endif
void half_adder_1bit(char a, char b, char *s, char *c) {
xor_gate(a, b, s);
and_gate(a, b, c);
}
void full_adder_1bit(char a, char b, char ci, char *s, char *co) {
char temp_s, temp_c;
half_adder_1bit(a, b, &temp_s, &temp_c);
half_adder_1bit(temp_s, ci, s, &temp_c);
or_gate(temp_c, temp_c, co);
}
void full_adder_2bit(const char *a, const char *b, char ci, char *s, char *co) {
char temp_c;
full_adder_1bit(a, b, ci, &s, &temp_c);
full_adder_1bit(a, b, temp_c, &s, co);
}
void full_adder_4bit(const char *a, const char *b, char ci, char *s, char *co) {
char temp_c;
full_adder_2bit(&a, &b, ci, &s, &temp_c);
full_adder_2bit(&a, &b, temp_c, &s, co);
}
void full_adder_8bit(const char *a, const char *b, char ci, char *s, char *co) {
char temp_c;
full_adder_4bit(&a, &b, ci, &s, &temp_c);
full_adder_4bit(&a, &b, temp_c, &s, co);
}
void full_adder_16bit(const char *a, const char *b, char ci, char *s, char *co) {
char temp_c;
full_adder_8bit(&a, &b, ci, &s, &temp_c);
full_adder_8bit(&a, &b, temp_c, &s, co);
}
void full_adder_32bit(const char *a, const char *b, char ci, char *s, char *co) {
char temp_c;
full_adder_16bit(&a, &b, ci, &s, &temp_c);
full_adder_16bit(&a, &b, temp_c, &s, co);
}
void binary(char dest, const char *src) {
memset(dest, '0', 32);
size_t l = strlen(src);
strncpy(dest + (32 - l), src, l);
}
void format(char *dest, const char src) {
const char *p = NULL;
for(size_t i = 0; i < 32; ++i) {
if(src == '1') {p = &src; break;}
}
if(!p) p = src + 31;
while(p != src + 32) *dest++ = *p++;
*dest = '\0';
}
char *add(const char *a, const char *b) {
char *a_ = malloc(32), *b_ = malloc(32);
char *c = malloc(33);
binary(a_, a); binary(b_, b);
char ci = '0', co;
full_adder_32bit(a_, b_, ci, c, &co);
//format(c, c);
c = '\0';
free(a_); free(b_);
return c;
}
void neg(char num) {
for(size_t i = 0; i < 32; ++i) {
xor_gate('1', num, &num);
}
char ci = '0', co;
char one = "00000000000000000000000000000001";
full_adder_32bit(num, one, ci, num, &co);
}
char *sub(const char *a, const char *b) {
char *a_ = malloc(32), *b_ = malloc(32);
char *c = malloc(33);
binary(a_, a); binary(b_, b);
neg(b_);
char ci = '0', co;
full_adder_32bit(a_, b_, ci, c, &co);
//format(c, c);
c = '\0';
free(a_); free(b_);
return c;
}
uint32_t number(const char n) {
uint32_t rv = 0;
const char *p = n;
for(uint32_t mask = 0x80000000; mask; mask >>= 1) {
if(*p++ == '1') rv |= mask;
}
return rv;
}
int main(void) {
char a;
char b;
scanf("%32s", a);
scanf("%32s", b);
char *c0 = add(a, b);
puts(c0);
uint32_t cu0 = number(c0);
printf("%u\n", cu0);
if((int32_t)cu0 > 1) printf("大于1\n");
free(c0);
char *c1 = sub(a, b);
puts(c1);
uint32_t cu1 = number(c1);
printf("%d\n", (int32_t)cu1);
if((int32_t)cu1 < -1) printf("小于-1\n");
free(c1);
return 0;
}
$ gcc -g -Wall -shared -o main.dll main.c
$ ls
main.cmain.dll
$ file main.dll
main.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows
$ python
Python 3.8.12 (default, Nov 23 2021, 20:18:25)
on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> dll = ctypes.cdll.LoadLibrary('main.dll')
>>> dll
<CDLL 'main.dll', handle 509660000 at 0x6fffffec79d0>
>>> dll.main()
10110110
1001
00000000000000000000000010111111
191
大于1
00000000000000000000000010101101
173
0
>>> dll.add(b'10011100', b'100101')
1633360
>>> dll.add.restype = ctypes.c_char_p
>>> dll.add(b'10011100', b'100101')
b'00000000000000000000000011000001'
>>>
$
学会百度,百度上面啥都有
hrpzcf 发表于 2022-10-20 16:48
首先得把c中需要在外部调用的函数调用约定限制为__cdecl,然后把c编译为动态库,Linux下用gcc编译器,windo ...
要是我给你一个c文件你能帮我转换一下吗?只要能在Python里调用就可以。 2wsx 发表于 2022-10-20 18:34
要是我给你一个c文件你能帮我转换一下吗?只要能在Python里调用就可以。
要是c项目不复杂等晚上有空可以帮你试试,楼上的大佬也行,他更专业 hrpzcf 发表于 2022-10-20 19:01
要是c项目不复杂等晚上有空可以帮你试试,楼上的大佬也行,他更专业
#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>
/*define read_pci_config*/
static unsigned char read_pci_config(unsigned int bus, unsigned int dev, unsigned int fun, unsigned int offset)
{
unsigned int value;
outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8)|offset,0xcf8);
value=inb(0xcfc+(offset&3));
return value;
}
/*define write_pci_config*/
void write_pci_config(unsigned int bus,unsigned int dev,unsigned int fun,unsigned int offset,unsigned int value)
{
outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8)|offset,0xcf8);
outb(value,0xcfc+(offset&3));
}
/*enumerate pci device by access CF8h CFCh port*/
int main()
{
iopl(3);
unsigned int offset;
unsigned int bus;
unsigned int dev;
unsigned int fun;
unsigned int data;
unsigned char act;
unsigned int count = 0;
while(1)
{
printf("\nplease select functions:\n");
printf("A:show all pci device\n");
printf("B:show specific device configuration space\n");
printf("0:quit\n");
scanf("%c",&act);
while(getchar()!='\n');
switch(act)
{
case 'A':
{
for(bus=0; bus<256; bus++)/*enumerate pci device*/
{
for(dev=0; dev<32; dev++)
{
for(fun=0; fun<8; fun++)
{
outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8),0xcf8);/* write address into address register*/
data=inl(0xcfc);/*obtain vendor ID from data register */
if(data!=0xffffffff)
{
count++;
printf("bus#:%2x\t\t dev#:%2x\t fun#:%2x\t Device ID:%02x\t\t Vendor ID:%02x\n",bus,dev,fun,data>>16,data);
}
}
}
}
printf("Total devices: %d",count);
printf("\n");
break;
}
case 'B':
{
printf("please input bus# dev# fun# to show specific device configuration space:");
scanf("%2x\t%2x\t%2x", &bus,&dev,&fun);
outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8),0xcf8);
data=inl(0xcfc);
while(1)
{
if(data!=0xffffffff)
{
printf("\n00:");
for(offset=0x00;offset<=0xff;offset++)
{
printf("%02x ",read_pci_config(bus,dev,fun,offset));
if(((offset+1)%16==0)&&(offset<255))
{
printf("\n%02x:",(offset+1)/16*0x10);
}
}
break;
}
else
continue;
}
printf("\n");
break;
}
case '0':
return;break;
default:
return;break;
}
}
return 0;
} 2wsx 发表于 2022-10-20 19:26
啊这个是有入口函数的呀,编译成可执行文件直接执行不好吗 本帖最后由 hrpzcf 于 2022-10-20 20:11 编辑
2wsx 发表于 2022-10-20 19:26
调用环境为 Linux,因为 #include <sys/io.h> 在 Linux 下才有
hrpzcf 发表于 2022-10-20 20:09
调用环境为 Linux,因为 #include在 Linux 下才有
好吧我试了执行了一下出现 Segmentation fault 段错误,不知道是我执行环境的问题还是 c 代码有误,不知道你这个 c 是什么环境下用的? hrpzcf 发表于 2022-10-20 20:16
好吧我试了执行了一下出现 Segmentation fault 段错误,不知道是我执行环境的问题还是 c 代码有误,不知 ...
在Linux下用GCC,我试过了可以正常运行。 2wsx 发表于 2022-10-21 08:21
在Linux下用GCC,我试过了可以正常运行。
我是有需求需要在Python下调用这个c代码 人造人 发表于 2022-10-20 18:20
大佬你这个代码怎么用啊,我没看懂{:10_266:} 2wsx 发表于 2022-10-21 08:41
大佬你这个代码怎么用啊,我没看懂
代码都给你贴出来了,使用的指令也给你贴出来了
你哪里看不懂?
你得有基础才能玩这些东西呀
上面那个C代码是一个32位的全加器
用add函数包装了一下,让这个全加器更方便使用
上面的例子首先把这个C代码编译成dll
然后在python中调用
调用了C代码中的main函数和add函数
2wsx 发表于 2022-10-21 08:22
我是有需求需要在Python下调用这个c代码
可这C代码,你走通了吗,能用吗? 段错误,有没有?
其实要生成 动态库(共享库)也不难,就两句gcc命令(gcc -c ... ; gcc -shared ...),python调用也是两三句。
但c代码本身有bug,或环境不对等问题,就很难搞咯。 2wsx 发表于 2022-10-21 08:21
在Linux下用GCC,我试过了可以正常运行。
那你下载我的附件试看能运行吗 hrpzcf 发表于 2022-10-21 14:08
那你下载我的附件试看能运行吗
C:\Users\Drayce\AppData\Local\Programs\Python\Python39\python.exe C:/Users/Austin/Downloads/call/call/pycall.py
Traceback (most recent call last):
File "C:\Users\Austin\Downloads\call\call\pycall.py", line 6, in <module>
inst = ctypes.CDLL("./libcall.so")
File "C:\Users\Drayce\AppData\Local\Programs\Python\Python39\lib\ctypes\__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
OSError: %1 不是有效的 Win32 应用程序。
Process finished with exit code 1
上面这些是运行结果
我用的是pycharm 好像运行不出来 2wsx 发表于 2022-10-21 19:15
C:%users\Drayce\AppData\Local\Programs\Python\Python39\python.exe C:/Users/Austin/Downloads/call/c ...
我不是说在Linux环境下运行了吗{:10_250:} hrpzcf 发表于 2022-10-21 19:17
我不是说在Linux环境下运行了吗
因为头文件的原因所以在Windows下就一定运行不了是吗
因为我现在希望能在Windows下pycharm里运行
页:
[1]
2