从 Python 编译的 C DLL 调用简单的“Hello World!” 函数会导致 OSError: exception: access violation

Calling simple "Hello World!" function from a compiled C DLL from Python results in OSError: exception: access violation

提问人:Carlos 提问时间:11/17/2023 最后编辑:John CarterCarlos 更新时间:11/17/2023 访问量:79

问:

C 代码:

// my_module.c

#include <stdio.h>

__declspec(dllexport)
void hello() {
    printf("Hello World!\n");
}

__declspec(dllexport)
int add_numbers(int a, int b) {
    return a + b;
}

// entry point
int main() {
    return 0;
}

构建脚本:

# build.py

from setuptools._distutils.ccompiler import new_compiler

compiler = new_compiler()
compiler.compile(["my_module.c"])
compiler.link_shared_lib(["my_module.obj"], "my_module")

主脚本:

# main.py

import ctypes

my_module = ctypes.CDLL("./my_module.dll")

my_module.add_numbers.argtypes = ctypes.c_int, ctypes.c_int
my_module.add_numbers.restype = ctypes.c_int

my_module.hello.argtypes = ()
my_module.hello.restype = None

result = my_module.add_numbers(3, 4)
print(type(result), result)

my_module.hello()

运行后,dll 的创建没有问题。但是,在运行时,“add_numbers”函数有效,但调用“hello”函数会导致“OSError:异常:访问冲突写入0x0000000000002C44”。python build.pypython main.py

我错过了什么吗?我是否需要以某种方式告诉编译器包含“stdio.h”标头?

python c windows dll 链接器

评论

0赞 Allan Wind 11/17/2023
您应该标记此窗口。只需进行一些更改(.obj 到 .o,my_module.dll 到 libmy_mobile.so),这适用于 Linux。#define __declspec(...)

答:

3赞 Ahmed AEK 11/17/2023 #1

似乎错误地链接了 msvc CRT。distutils

您不应导入任何带有下划线的内容,例如 ,因为它不是公共 API 的一部分,因此不应使用它。_distutils

由于这是一个简单的 Windows DLL,您可以直接调用并编译它。(请确保在执行此操作之前打开命令提示符)cl.exex64 Native Tools Command Prompt for VS 2022

cl.exe /LD my_module.c

这将起作用,但是如果您有更多文件,那么您可能应该为它创建一个项目并使用它来从 python 构建您的 C dll。cmake

快速浏览一下从 生成的依赖关系distutils

enter image description here

与直接的那个相比。cl.exe

enter image description here

将所有额外的依赖项从 Windows SDK 复制到 DLL 文件夹应该可以使其正常工作,但这不是正确的方法。