如何从Python调用含Char**与int*参数的C方法?附代码求助
Fixing Parameter Passing for
getContourResults in ctypes Hey there, let's walk through fixing your parameter passing issue for getContourResults step by step. I've gone through your code and spotted a few key mismatches between your Python ctypes setup and the C function signature—here's how to get it working correctly:
Key Issues in Your Current Code
- String Type Mismatch: Your C function uses
char*(UTF-8/ASCII strings), but you're passingc_wchar_p(wide Unicode strings) in Python. This will cause encoding errors and memory misalignment. - Invalid
argtypesDefinitions: You're using instance-specific types likeself.select_typeinargtypes—this won't work becauseargtypesrequires standard ctypes type objects, not custom array instances tied to a class. - Unconverted String Parameters: Strings like
filename,stagename, andentitytypearen't converted to the byte format that C'schar*expects.
Fixed Python Code (module.py)
import sys from ctypes import * # Load the DLL (ensure the path is correct) dll = CDLL('D:\\erf_utils_python\\erf_utils_io.dll') getContourResults = dll.getContourResults class Utility(object): def __init__(self): print('i am inside init') self.stagename = "post".encode('utf-8') # Encode to bytes for C char* self.stateids = (c_int * 1)(2934) self.stateidcount = 1 self.entityidcount = 1 self.entityid = (c_int * 1)(1) self.entitytype = "FPM".encode('utf-8') # Encode to bytes self.variablecount = 1 self.ores = (c_float * 1)(1.0) # Use c_float array instead of Python list for pointer access self.filename = 'allinone_RESULT.erfh5'.encode('utf-8') # Encode to bytes # Handle char** for variablegroup: create c_char_p array self.variablegroup = ["FPM_Mach_Number"] var_group_len = len(self.variablegroup) self.select_type = (c_char_p * var_group_len) self.select = self.select_type() for idx, item in enumerate(self.variablegroup): self.select[idx] = item.encode('utf-8') # Encode each string to bytes # Handle char** for variable: create c_char_p array self.variable = ["FPM_Mach_Number"] var_len = len(self.variable) self.var_type = (c_char_p * var_len) self.variable_list = self.var_type() for idx, item in enumerate(self.variable): self.variable_list[idx] = item.encode('utf-8') # Encode each string to bytes def run(self): # Define argtypes with standard ctypes types matching the C signature getContourResults.argtypes = [ c_char_p, # char* iFilename c_char_p, # char* iStagename c_int, # int iStateidCnt POINTER(c_int), # int* Stateids c_int, # int iEntityIdCount POINTER(c_int), # int* iEntityids c_char_p, # char* iEntityType c_int, # int iVariablecnt POINTER(c_char_p), # char** iVariablegroup POINTER(c_char_p), # char** ivariable POINTER(c_float) # float* oResults ] getContourResults.restype = c_int # Call the function with properly formatted parameters err = getContourResults( self.filename, self.stagename, self.stateidcount, self.stateids, self.entityidcount, self.entityid, self.entitytype, self.variablecount, self.select, self.variable_list, self.ores ) print(f"Function returned error code: {err}") print(f"Result value: {self.ores[0]}") # Access the result from the c_float array reader = Utility() reader.run()
Breakdown of Critical Fixes
- String Encoding: All strings passed to C
char*parameters are encoded to UTF-8 bytes using.encode('utf-8'), which matches what C expects forchar*strings. char**Handling: For thechar**parameters (iVariablegroupandivariable), we create ac_char_parray where each element is an encoded byte string. When passed to the function, this array is automatically treated as achar**(pointer to pointer) in C.- Valid
argtypes: We use standard ctypes type objects inargtypesthat exactly mirror the C function's signature. This helps ctypes correctly marshal data between Python and C. - Result Storage: Instead of using a Python list for
ores, we use ac_floatarray. This allows C to write directly to the memory location that Python can access later.
内容的提问来源于stack exchange,提问作者sand
相关产品推荐
相关产品推荐

