为何我在简单ctypes示例中遇到Access Violation错误?
Let's break down why you're hitting that access violation and how to fix it quickly.
The Root Cause
The problem boils down to missing type annotations for your AComplicatedCPPObj_new function in Python. By default, ctypes assumes every function returns a 32-bit c_int—but on 64-bit systems, pointers are 8 bytes wide. When your C wrapper returns a pointer to the C++ object, ctypes truncates that 8-byte address to 4 bytes, leaving you with an invalid, garbage pointer stored in self.obj. When you try to use that broken pointer in getA, it tries to access a non-existent memory address, triggering the access violation.
The Fix
You need to explicitly define argtypes and restype for all C functions you call via ctypes. Here's the corrected Python code:
import ctypes as c import os, glob, sys WORKING_DIRECTORY = os.path.dirname(__file__) if sys.platform == "linux": so_path = os.path.join(WORKING_DIRECTORY, "INSTALL/lib/libctypesTest.so") else: so_path = os.path.join(WORKING_DIRECTORY, "INSTALL/bin/ctypesTest.dll") if not os.path.isfile(so_path): raise FileNotFoundError(so_path) lib = c.CDLL(so_path) # Set up types for all exported functions ONCE, outside the class lib.AComplicatedCPPObj_new.argtypes = [c.c_int] lib.AComplicatedCPPObj_new.restype = c.c_void_p lib.AComplicatedCPPObj_getA.argtypes = [c.c_void_p] lib.AComplicatedCPPObj_getA.restype = c.c_int class AComplicatedCPPObj: def __init__(self, a): self.obj = lib.AComplicatedCPPObj_new(a) def getA(self): return lib.AComplicatedCPPObj_getA(self.obj) if __name__ == '__main__': o = AComplicatedCPPObj(4) print(o) print(o.getA()) # This should now output 4 without errors
Key Changes Explained
- Added type info for
AComplicatedCPPObj_new:argtypes = [c.c_int]tells ctypes the function expects an integer input (matching your C wrapper's parameter).restype = c.c_void_pspecifies the function returns a void pointer (which aligns with the C++ object pointer returned by the wrapper).
- Moved type setup outside
__init__: You only need to configure these types once when loading the library, not every time you create an instance of the Python class.
Extra Tips to Avoid Future Issues
- Always define
argtypesandrestypefor every ctypes function you use. This catches type mismatches early and prevents undefined behavior like access violations. - On Windows, ensure your exported functions use the correct calling convention: your
extern "C"wrapper usescdecl, which matchesctypes.CDLL(if you usedstdcall, you'd needctypes.WinDLLinstead).
内容的提问来源于stack exchange,提问作者CiaranWelsh

