在Windows11 下 测试python ctypes

最近想试一下python调用c会不会更快,看了大佬的文章打算用ctypes尝试以下,记录以下过程和bugs。

环境:

系统

版本    Windows 11 专业版
版本    22H2
安装日期    ‎2023/‎3/‎25
操作系统版本    22621.1555
体验    Windows Feature Experience Pack 1000.22640.1000.0

编译器

MSVC  cl.exe  用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.35.32216.1 版

Python

3.11.1
 

IDE:

Clion 2022.3.1

首先在项目目录创建cpp文件,gm.cpp:

int gm() {
    return 1;
}

int add(int a, int b) {
    return a + b;
}

在clion的终端执行cl,编译成dll文件:

cl /LD gm.cpp  /o gm.dll

但是!
会报错:LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”

google一搜,原来这些编译都是要在VS的终端中进行,于是打开 Visual Studio 2022 Developer Command Prompt v17.5.3 

编译,成功!在项目目录得到了:

 写段python,test.py,运行:

from ctypes import *

great_module = CDLL('./gm.dll')
print(great_module.gm(13))
add = great_module.add
print(add(41, 1))

嗯?又报错:

Traceback (most recent call last):
  File "E:\works\c&c++\Cpython\test.py", line 4, in <module>
    print(great_module.gm(13))
          ^^^^^^^^^^^^^^^
  File "D:\Python311\Lib\ctypes\__init__.py", line 389, in __getattr__
    func = self.__getitem__(name)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python311\Lib\ctypes\__init__.py", line 394, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: function 'gm' not found

为啥没找到函数gm?继续Google。。。

原来是要定义一下,声明为可以被找到的函数,gm.cpp改成:

extern "C" {
int gm();
int add(int a, int b);
}
int gm() {
    return 1;
}

int add(int a, int b) {
    return a + b;
}

再次编译,运行,还是报错?再搜,再改:

原来是MSVC的问题,它也要看个声明,那就加呗:

#ifdef _MSC_VER
#define DLL_EXPORT __declspec( dllexport )
#else
#define DLL_EXPORT
#endif
extern "C" {
DLL_EXPORT int gm();
DLL_EXPORT int add(int a, int b);
}

DLL_EXPORT int gm() {
    return 1;
}

DLL_EXPORT int add(int a, int b) {
    return a + b;
}

再次编译,运行,成功了!

 测测速度:

from ctypes import *

great_module = CDLL('./gm.dll')
add = great_module.add

import time

t = time.perf_counter()
for i in range(10000000):
    10000 + 20000
print(time.perf_counter() - t)

t = time.perf_counter()
for i in range(10000000):
    add(10000, 20000)
print(time.perf_counter() - t)

为啥更慢呢?

 把循环放到c的函数里试试,改gm.cpp:

#ifdef _MSC_VER
#define DLL_EXPORT __declspec( dllexport )
#else
#define DLL_EXPORT
#endif
extern "C" {
DLL_EXPORT int gm();
DLL_EXPORT int add(int a, int b);
DLL_EXPORT int for_add(int a, int b);
}

DLL_EXPORT int gm() {
    return 1;
}

DLL_EXPORT int add(int a, int b) {
    return a + b;
}

DLL_EXPORT int for_add(int a, int b) {
    for (int i = 0; i < 10000000; ++i) {
        a + b;
    }
    return a + b;
}

改test.py:

from ctypes import *

great_module = CDLL('./gm.dll')
for_add = great_module.for_add

import time
# t = time.perf_counter()
# print(time.perf_counter() - t)



t = time.perf_counter()
for i in range(10000000):
    10000 + 20000
print(time.perf_counter() - t)

t = time.perf_counter()
for_add(10000,20000)
print(time.perf_counter() - t)

似乎这样c就快了很多:

  应该是从dll中调用这一步骤要花费比较长的时间,减少调用次数就可以加速?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值