python - 在 Python 中使用 ctypes.CDLL 调用 ac 函数时,函数总是将 0 作为参数传递
问题描述
我试图调用的 c 函数:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
long long int n = atoll(argv[1]);
printf("main(%lld)\n", n);
int m = 0;
while (n > 1) {
m++;
if (n % 2 == 0) { // even
printf("%lld = %lld/2 \n", n/2, n);
n = n/2;
}
else {
printf("%lld = 3*%lld+1 \n", 3*n+1, n);
n = 3*n + 1;
}
}
printf("Collatz(%lld) is '%d'\n", n,m);
return m;
}
我的 python 代码尝试使用参数 4 调用它
from ctypes import *
import os, sys
print("you typed:", sys.argv[1])
filename = sys.argv[1].split(".")[0]
os.system(f"gcc -c -fPIC {filename}.c -o {filename}.o && gcc {filename}.o " \
f"-shared -o {filename}.so")
soFile = CDLL(os.getcwd() + "/" + filename + ".so")
soFile.main(4) # <----------
在 vim 中,我运行以下命令:
:!python test.py "collatz-loop"
you typed: collatz-loop
main(0)
Collatz(0) is '0'
注意输出如何为 0。即使我将参数更改为 4 以外的值,输出始终为 0。
如果我尝试更改soFile.main(4)
为具有两个参数的东西,例如soFile.main(2, 4)
,我得到
:!python test.py "collatz-loop"
shell returned 139
为什么会发生这种情况,我该如何解决?
- 顺便说一句,我对 c 很陌生,虽然对 Java 很熟悉。它们在语法上看起来非常相似。
- 是的,我确实记得在运行 .py 文件之前保存/写入 python 和 c 文件。
解决方案
评论线程的 TLDR:您应该将其拆分为 2 个函数,main
并且collatz
( int collatz(long long n)
) 并使 main 只传递atoll(argv[1])
给 collatz,因此您可以将其作为可执行文件正常运行,也可以从 python 脚本文件作为共享库运行。您还需要将 ctypes 中的 argtype 设置为 long long(我认为它默认为 int)。
C:
#include <stdio.h>
#include <stdlib.h>
int collatz(long long n){
int m = 0;
while (n > 1) {
m++;
if (n % 2 == 0) { // even
printf("%lld = %lld/2 \n", n/2, n);
n = n/2;
}
else {
printf("%lld = 3*%lld+1 \n", 3*n+1, n);
n = 3*n + 1;
}
}
printf("Collatz(%lld) is '%d'\n", n,m);
return m;
}
int main(int argc, char *argv[]){
long long int n = atoll(argv[1]);
printf("main(%lld)\n", n);
collatz(n);
}
Python:
from ctypes import *
import os, sys
print("you typed:", sys.argv[1])
filename = sys.argv[1].split(".")[0]
os.system(f"gcc -c -fPIC {filename}.c -o {filename}.o && gcc {filename}.o " \
f"-shared -o {filename}.so")
soFile = CDLL(os.getcwd() + "/" + filename + ".so")
soFile.collatz.argtypes = [c_longlong]
soFile.collatz(4)
注意:与此问题没有直接关系,但您应该检查以确保argc > 2
在您的 C 代码中避免在没有传递参数的情况下越界读取。
推荐阅读
- regex - VBA RegEx:如何在特定字符串之后找到数字的第一个实例并忽略所有其他字符?
- git - 使用 Ansible 向 Azure Repo 添加、提交、推送
- javascript - 在另一个文件检查时返回
- visual-studio - 查找预编译头时出现错误 C1010 文件意外结束
- c# - 带有对象列表的 LINQ Where 查询
- xcode - 解决拉取请求中的合并冲突是 Azure Dev ops 中的 xcode
- kubernetes - 错误:升级失败:升级前挂钩失败:等待条件超时
- redirect - 如何将 squarespace 页面 url 重定向到非 squarespace 子域
- cmake - 使用 ExternalProject 时暂停主 CMake
- python - python:创建unicode字符串的chararray