鱼C论坛

 找回密码
 立即注册
查看: 4768|回复: 20

动态链接库

[复制链接]
发表于 2022-10-20 14:03:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
如何将c文件转换成DLL文件并在python中调用?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-20 16:48:17 From FishC Mobile | 显示全部楼层
首先得把c中需要在外部调用的函数调用约定限制为__cdecl,然后把c编译为动态库,Linux下用gcc编译器,windows下用msvc或者mingw64的gcc都可以。Python代码中使用ctype加载动态库就可以调用了。具体两三句话说不清楚。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 18:13:43 | 显示全部楼层
本帖最后由 阿奇_o 于 2022-10-20 18:19 编辑

我看你骨骼惊奇,直接给你以下秘籍:《C草巨蟒之DLL神掌》。。 能修炼到什么程度,就看你造化了,哈哈哈
 
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 
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 18:20:44 | 显示全部楼层
$ 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[2];
    half_adder_1bit(a, b, &temp_s, &temp_c[0]);
    half_adder_1bit(temp_s, ci, s, &temp_c[1]);
    or_gate(temp_c[0], temp_c[1], co);
}

void full_adder_2bit(const char *a, const char *b, char ci, char *s, char *co) {
    char temp_c;
    full_adder_1bit(a[1], b[1], ci, &s[1], &temp_c);
    full_adder_1bit(a[0], b[0], temp_c, &s[0], co);
}

void full_adder_4bit(const char *a, const char *b, char ci, char *s, char *co) {
    char temp_c;
    full_adder_2bit(&a[2], &b[2], ci, &s[2], &temp_c);
    full_adder_2bit(&a[0], &b[0], temp_c, &s[0], co);
}

void full_adder_8bit(const char *a, const char *b, char ci, char *s, char *co) {
    char temp_c;
    full_adder_4bit(&a[4], &b[4], ci, &s[4], &temp_c);
    full_adder_4bit(&a[0], &b[0], temp_c, &s[0], co);
}

void full_adder_16bit(const char *a, const char *b, char ci, char *s, char *co) {
    char temp_c;
    full_adder_8bit(&a[8], &b[8], ci, &s[8], &temp_c);
    full_adder_8bit(&a[0], &b[0], temp_c, &s[0], co);
}

void full_adder_32bit(const char *a, const char *b, char ci, char *s, char *co) {
    char temp_c;
    full_adder_16bit(&a[16], &b[16], ci, &s[16], &temp_c);
    full_adder_16bit(&a[0], &b[0], temp_c, &s[0], co);
}

void binary(char dest[const 32], 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 32]) {
    const char *p = NULL;
    for(size_t i = 0; i < 32; ++i) {
        if(src[i] == '1') {p = &src[i]; 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[32] = '\0';
    free(a_); free(b_);
    return c;
}

void neg(char num[const 32]) {
    for(size_t i = 0; i < 32; ++i) {
        xor_gate('1', num[i], &num[i]);
    }
    char ci = '0', co;
    char one[32] = "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[32] = '\0';
    free(a_); free(b_);
    return c;
}

uint32_t number(const char n[const 32]) {
    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[33];
    char b[33];
    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.c  main.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)
[GCC 11.2.0] 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'
>>>
$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 18:24:42 | 显示全部楼层
学会百度,百度上面啥都有
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-20 18:34:03 | 显示全部楼层
hrpzcf 发表于 2022-10-20 16:48
首先得把c中需要在外部调用的函数调用约定限制为__cdecl,然后把c编译为动态库,Linux下用gcc编译器,windo ...

要是我给你一个c文件你能帮我转换一下吗?只要能在Python里调用就可以。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 19:01:00 From FishC Mobile | 显示全部楼层
2wsx 发表于 2022-10-20 18:34
要是我给你一个c文件你能帮我转换一下吗?只要能在Python里调用就可以。

要是c项目不复杂等晚上有空可以帮你试试,楼上的大佬也行,他更专业
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-20 19:26:06 | 显示全部楼层
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;
}                        
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 20:07:20 | 显示全部楼层

啊这个是有入口函数的呀,编译成可执行文件直接执行不好吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 20:09:05 | 显示全部楼层
本帖最后由 hrpzcf 于 2022-10-20 20:11 编辑


调用环境为 Linux,因为 #include <sys/io.h> 在 Linux 下才有

call.zip (4.58 KB, 下载次数: 1)

2022-10-20_200533.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 20:16:56 | 显示全部楼层
hrpzcf 发表于 2022-10-20 20:09
调用环境为 Linux,因为 #include  在 Linux 下才有

好吧我试了执行了一下出现 Segmentation fault 段错误,不知道是我执行环境的问题还是 c 代码有误,不知道你这个 c 是什么环境下用的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-21 08:21:54 | 显示全部楼层
hrpzcf 发表于 2022-10-20 20:16
好吧我试了执行了一下出现 Segmentation fault 段错误,不知道是我执行环境的问题还是 c 代码有误,不知 ...

在Linux下用GCC,我试过了可以正常运行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-21 08:22:41 | 显示全部楼层
2wsx 发表于 2022-10-21 08:21
在Linux下用GCC,我试过了可以正常运行。

我是有需求需要在Python下调用这个c代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-21 08:41:07 | 显示全部楼层

大佬你这个代码怎么用啊,我没看懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-21 09:12:28 | 显示全部楼层
2wsx 发表于 2022-10-21 08:41
大佬你这个代码怎么用啊,我没看懂

代码都给你贴出来了,使用的指令也给你贴出来了
你哪里看不懂?
你得有基础才能玩这些东西呀


上面那个C代码是一个32位的全加器
用add函数包装了一下,让这个全加器更方便使用
上面的例子首先把这个C代码编译成dll
然后在python中调用
调用了C代码中的main函数和add函数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-21 10:03:02 | 显示全部楼层
2wsx 发表于 2022-10-21 08:22
我是有需求需要在Python下调用这个c代码

可这C代码,你走通了吗,能用吗? 段错误,有没有?
其实要生成 动态库(共享库)也不难,就两句gcc命令(gcc -c ... ; gcc -shared ...),python调用也是两三句。
但c代码本身有bug,或环境不对等问题,就很难搞咯。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-21 14:08:01 From FishC Mobile | 显示全部楼层
2wsx 发表于 2022-10-21 08:21
在Linux下用GCC,我试过了可以正常运行。

那你下载我的附件试看能运行吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-21 19:15:38 | 显示全部楼层
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: [WinError 193] %1 不是有效的 Win32 应用程序。

Process finished with exit code 1



上面这些是运行结果
我用的是pycharm 好像运行不出来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-21 19:17:34 From FishC Mobile | 显示全部楼层
2wsx 发表于 2022-10-21 19:15
C:%users\Drayce\AppData\Local\Programs\Python\Python39\python.exe C:/Users/Austin/Downloads/call/c ...

我不是说在Linux环境下运行了吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-22 10:04:30 | 显示全部楼层
hrpzcf 发表于 2022-10-21 19:17
我不是说在Linux环境下运行了吗

因为头文件的原因所以在Windows下就一定运行不了是吗
因为我现在希望能在Windows下pycharm里运行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-25 23:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表