鱼C论坛

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

动态链接库

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

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

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

x
如何将c文件转换成DLL文件并在python中调用?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

使用道具 举报

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

我看你骨骼惊奇,直接给你以下秘籍:《C草巨蟒之DLL神掌》。。 能修炼到什么程度,就看你造化了,哈哈哈

  1. from ctypes import *

  2. #----------以下四种加载DLL方式皆可—————————
  3. # pDLL = WinDLL("./myTest.dll")
  4. # pDll = windll.LoadLibrary("./myTest.dll")
  5. # pDll = cdll.LoadLibrary("./myTest.dll")
  6. pDll = CDLL("./TestDLL.dll")  # 注意写全路径或相对路径


  7. # 旧的cpp的例子:
  8. # https://www.cnblogs.com/FHC1994/p/11421229.html
  9. #调用动态链接库函数
  10. # res = pDll.sum(1,2)  # 旧的cpp加法的例子,返回 a+b
  11. #打印返回结果
  12. # print(res)


  13. # 新例子(用gcc如何将c生成dll):
  14. # https://www.bilibili.com/video/BV1E4411z7Ua/?vd_source=691572ece9556ac42935a92fe9cf7e76
  15. # https://www.codementor.io/@a_hathon/building-and-using-dlls-in-c-d7rrd4caz

  16. # msg = pDll.message()
  17. # print(msg)    # 这样会多出两个11 (异常?)

  18. pDll.message()  # 这样即可,因为它本身就是用C的printf()打印到stdout
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 18:20:44 | 显示全部楼层
  1. $ ls
  2. main.c
  3. $ cat main.c
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <stdint.h>

  8. void and_gate(char a, char b, char *c) {
  9.     *c = a == '1' && b == '1' ? '1' : '0';
  10. }

  11. void or_gate(char a, char b, char *c) {
  12.     *c = a == '0' && b == '0' ? '0' : '1';
  13. }

  14. #if 0
  15. void xor_gate(char a, char b, char *c) {
  16.     *c = a != b ? '1' : '0';
  17. }
  18. #else
  19. void not_gate(char a, char *b) {
  20.     *b = a == '1' ? '0' : '1';
  21. }

  22. void xor_gate(char a, char b, char *c) {
  23.     char na, nb;
  24.     char r0, r1;
  25.     not_gate(a, &na);
  26.     not_gate(b, &nb);
  27.     and_gate(a, nb, &r0);
  28.     and_gate(b, na, &r1);
  29.     or_gate(r0, r1, c);
  30. }
  31. #endif

  32. void half_adder_1bit(char a, char b, char *s, char *c) {
  33.     xor_gate(a, b, s);
  34.     and_gate(a, b, c);
  35. }

  36. void full_adder_1bit(char a, char b, char ci, char *s, char *co) {
  37.     char temp_s, temp_c[2];
  38.     half_adder_1bit(a, b, &temp_s, &temp_c[0]);
  39.     half_adder_1bit(temp_s, ci, s, &temp_c[1]);
  40.     or_gate(temp_c[0], temp_c[1], co);
  41. }

  42. void full_adder_2bit(const char *a, const char *b, char ci, char *s, char *co) {
  43.     char temp_c;
  44.     full_adder_1bit(a[1], b[1], ci, &s[1], &temp_c);
  45.     full_adder_1bit(a[0], b[0], temp_c, &s[0], co);
  46. }

  47. void full_adder_4bit(const char *a, const char *b, char ci, char *s, char *co) {
  48.     char temp_c;
  49.     full_adder_2bit(&a[2], &b[2], ci, &s[2], &temp_c);
  50.     full_adder_2bit(&a[0], &b[0], temp_c, &s[0], co);
  51. }

  52. void full_adder_8bit(const char *a, const char *b, char ci, char *s, char *co) {
  53.     char temp_c;
  54.     full_adder_4bit(&a[4], &b[4], ci, &s[4], &temp_c);
  55.     full_adder_4bit(&a[0], &b[0], temp_c, &s[0], co);
  56. }

  57. void full_adder_16bit(const char *a, const char *b, char ci, char *s, char *co) {
  58.     char temp_c;
  59.     full_adder_8bit(&a[8], &b[8], ci, &s[8], &temp_c);
  60.     full_adder_8bit(&a[0], &b[0], temp_c, &s[0], co);
  61. }

  62. void full_adder_32bit(const char *a, const char *b, char ci, char *s, char *co) {
  63.     char temp_c;
  64.     full_adder_16bit(&a[16], &b[16], ci, &s[16], &temp_c);
  65.     full_adder_16bit(&a[0], &b[0], temp_c, &s[0], co);
  66. }

  67. void binary(char dest[const 32], const char *src) {
  68.     memset(dest, '0', 32);
  69.     size_t l = strlen(src);
  70.     strncpy(dest + (32 - l), src, l);
  71. }

  72. void format(char *dest, const char src[const 32]) {
  73.     const char *p = NULL;
  74.     for(size_t i = 0; i < 32; ++i) {
  75.         if(src[i] == '1') {p = &src[i]; break;}
  76.     }
  77.     if(!p) p = src + 31;
  78.     while(p != src + 32) *dest++ = *p++;
  79.     *dest = '\0';
  80. }

  81. char *add(const char *a, const char *b) {
  82.     char *a_ = malloc(32), *b_ = malloc(32);
  83.     char *c = malloc(33);
  84.     binary(a_, a); binary(b_, b);
  85.     char ci = '0', co;
  86.     full_adder_32bit(a_, b_, ci, c, &co);
  87.     //format(c, c);
  88.     c[32] = '\0';
  89.     free(a_); free(b_);
  90.     return c;
  91. }

  92. void neg(char num[const 32]) {
  93.     for(size_t i = 0; i < 32; ++i) {
  94.         xor_gate('1', num[i], &num[i]);
  95.     }
  96.     char ci = '0', co;
  97.     char one[32] = "00000000000000000000000000000001";
  98.     full_adder_32bit(num, one, ci, num, &co);
  99. }

  100. char *sub(const char *a, const char *b) {
  101.     char *a_ = malloc(32), *b_ = malloc(32);
  102.     char *c = malloc(33);
  103.     binary(a_, a); binary(b_, b);
  104.     neg(b_);
  105.     char ci = '0', co;
  106.     full_adder_32bit(a_, b_, ci, c, &co);
  107.     //format(c, c);
  108.     c[32] = '\0';
  109.     free(a_); free(b_);
  110.     return c;
  111. }

  112. uint32_t number(const char n[const 32]) {
  113.     uint32_t rv = 0;
  114.     const char *p = n;
  115.     for(uint32_t mask = 0x80000000; mask; mask >>= 1) {
  116.         if(*p++ == '1') rv |= mask;
  117.     }
  118.     return rv;
  119. }

  120. int main(void) {
  121.     char a[33];
  122.     char b[33];
  123.     scanf("%32s", a);
  124.     scanf("%32s", b);
  125.     char *c0 = add(a, b);
  126.     puts(c0);
  127.     uint32_t cu0 = number(c0);
  128.     printf("%u\n", cu0);
  129.     if((int32_t)cu0 > 1) printf("大于1\n");
  130.     free(c0);
  131.     char *c1 = sub(a, b);
  132.     puts(c1);
  133.     uint32_t cu1 = number(c1);
  134.     printf("%d\n", (int32_t)cu1);
  135.     if((int32_t)cu1 < -1) printf("小于-1\n");
  136.     free(c1);
  137.     return 0;
  138. }
  139. $ gcc -g -Wall -shared -o main.dll main.c
  140. $ ls
  141. main.c  main.dll
  142. $ file main.dll
  143. main.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows
  144. $ python
  145. Python 3.8.12 (default, Nov 23 2021, 20:18:25)
  146. [GCC 11.2.0] on cygwin
  147. Type "help", "copyright", "credits" or "license" for more information.
  148. >>> import ctypes
  149. >>> dll = ctypes.cdll.LoadLibrary('main.dll')
  150. >>> dll
  151. <CDLL 'main.dll', handle 509660000 at 0x6fffffec79d0>
  152. >>> dll.main()
  153. 10110110
  154. 1001
  155. 00000000000000000000000010111111
  156. 191
  157. 大于1
  158. 00000000000000000000000010101101
  159. 173
  160. 0
  161. >>> dll.add(b'10011100', b'100101')
  162. 1633360
  163. >>> dll.add.restype = ctypes.c_char_p
  164. >>> dll.add(b'10011100', b'100101')
  165. b'00000000000000000000000011000001'
  166. >>>
  167. $
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-20 18:24:42 | 显示全部楼层
学会百度,百度上面啥都有
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

要是我给你一个c文件你能帮我转换一下吗?只要能在Python里调用就可以。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

要是c项目不复杂等晚上有空可以帮你试试,楼上的大佬也行,他更专业
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-20 19:26:06 | 显示全部楼层
hrpzcf 发表于 2022-10-20 19:01
要是c项目不复杂等晚上有空可以帮你试试,楼上的大佬也行,他更专业
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/io.h>

  4. /*define read_pci_config*/
  5. static unsigned char read_pci_config(unsigned int bus, unsigned int dev, unsigned int fun, unsigned int offset)
  6. {
  7.         unsigned int value;
  8.         outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8)|offset,0xcf8);
  9.         value=inb(0xcfc+(offset&3));
  10.         return value;
  11. }

  12. /*define write_pci_config*/
  13. void write_pci_config(unsigned int bus,unsigned int dev,unsigned int fun,unsigned int offset,unsigned int value)
  14. {
  15.         outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8)|offset,0xcf8);
  16.         outb(value,0xcfc+(offset&3));
  17. }

  18. /*enumerate pci device by access CF8h CFCh port*/
  19. int main()
  20. {
  21.           iopl(3);
  22.         unsigned int offset;
  23.         unsigned int bus;
  24.         unsigned int dev;
  25.         unsigned int fun;
  26.         unsigned int data;
  27.         unsigned char act;
  28.         unsigned int count = 0;
  29.         while(1)
  30.         {
  31.                 printf("\nplease select functions:\n");
  32.                 printf("A:show all pci device\n");
  33.                 printf("B:show specific device configuration space\n");
  34.                 printf("0:quit\n");
  35.                 scanf("%c",&act);
  36.                 while(getchar()!='\n');
  37.                 switch(act)
  38.                 {
  39.                         case 'A':
  40.                         {
  41.                                 for(bus=0; bus<256; bus++)/*enumerate pci device*/
  42.                                 {
  43.                                         for(dev=0; dev<32; dev++)
  44.                                         {
  45.                                                 for(fun=0; fun<8; fun++)
  46.                                                 {
  47.                                                         outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8),0xcf8);/* write address into address register*/
  48.                                                         data=inl(0xcfc);/*obtain vendor ID from data register */
  49.                                                         if(data!=0xffffffff)
  50.                                                         {               
  51.                                                                 count++;
  52.                                                                 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);

  53.                                                         }
  54.                                                 }
  55.                                         }

  56.                                 }
  57.                                 printf("Total devices: %d",count);
  58.                                 printf("\n");
  59.                                 break;
  60.                         }
  61.                
  62.                         case 'B':
  63.                         {
  64.                                 printf("please input bus# dev# fun# to show specific device configuration space:");
  65.                                 scanf("%2x\t%2x\t%2x", &bus,&dev,&fun);
  66.                                 outl(0x80000000|(bus<<16)|(dev<<11)|(fun<<8),0xcf8);
  67.                                        data=inl(0xcfc);
  68.                                 while(1)
  69.                                 {
  70.                                         if(data!=0xffffffff)
  71.                                         {
  72.                                                 printf("\n00:");
  73.                                                 for(offset=0x00;offset<=0xff;offset++)
  74.                                                 {
  75.                                                         printf("%02x ",read_pci_config(bus,dev,fun,offset));
  76.                                                         if(((offset+1)%16==0)&&(offset<255))
  77.                                                         {
  78.                                                                 printf("\n%02x:",(offset+1)/16*0x10);
  79.                                                         }
  80.                                                 }
  81.                                                 break;
  82.                                         }
  83.                                         else
  84.                                                 continue;
  85.                                 }
  86.                                 printf("\n");
  87.                                 break;

  88.                         }
  89.                         case '0':
  90.                                 return;break;
  91.                         default:
  92.                                 return;break;
  93.                 }
  94.         }
  95.         return 0;
  96. }                       
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

啊这个是有入口函数的呀,编译成可执行文件直接执行不好吗
小甲鱼最新课程 -> https://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
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

在Linux下用GCC,我试过了可以正常运行。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

我是有需求需要在Python下调用这个c代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

大佬你这个代码怎么用啊,我没看懂
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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


上面那个C代码是一个32位的全加器
用add函数包装了一下,让这个全加器更方便使用
上面的例子首先把这个C代码编译成dll
然后在python中调用
调用了C代码中的main函数和add函数
小甲鱼最新课程 -> https://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,或环境不对等问题,就很难搞咯。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

那你下载我的附件试看能运行吗
小甲鱼最新课程 -> https://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 好像运行不出来
小甲鱼最新课程 -> https://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环境下运行了吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

因为头文件的原因所以在Windows下就一定运行不了是吗
因为我现在希望能在Windows下pycharm里运行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-25 12:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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