1

Here is a ctypes wrapper to call a DLL. It reads a simple text file as a byte array (utf-8 encoding), creates a string buffer of the same length, and passes both to the DLL. With the code below, I get the error: expected LP_c_char_p instance instead of c_char_Array_8049.

I have also tried passing the two arrays as ctypes.c_byte but that didn't work either.

file_name = r"C:\Projects\--Data_Files\Strings\Sample_Text.txt"
f = io.open(file_name, mode="r", encoding="utf-8")
CA_my_str = f.read()    

CA_no_punct = ctypes.create_string_buffer(len(CA_my_str))

Input_Length_Array = []
Input_Length_Array.append(len(CA_no_punct))
Input_Length_Array.append(len(CA_my_str))

length_array_out = (ctypes.c_double * len(Input_Length_Array))(*Input_Length_Array)

hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/String_Processing/String_Processing.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_char_p),ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_double)]
CallName.restype = ctypes.POINTER(ctypes.c_double)

ret_ptr = CallName(CA_no_punct, CA_my_str, length_array_out)

So the question is: what's the correct ctypes argtype for the two arrays CA_my_str and CA_no_punct?

EDIT: per request below, here is the entry point in NASM:

Main_Entry_fn:
push rdi
push rbp
mov [no_punct_ptr],rcx
mov [my_str_ptr],rdx
mov [data_master_ptr],r8
; Now assign lengths
lea rdi,[data_master_ptr]
mov rbp,[rdi]
xor rcx,rcx
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [no_punct_length],rax
add rcx,8
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [my_str_length],rax
add rcx,8
call String_Processing_fn
exit_label_for_Main_Entry_fn:
pop rbp
pop rdi
ret
6
  • Please edit your question to include the signature of the C method you are trying to call (Main_Entry_Fn). Commented Mar 8, 2018 at 21:39
  • The dll is written in assembler (NASM) which does not have signatures like C -- instead, parameters are passed in registers. I've included it above, but it doesn't reveal the problem. Commented Mar 8, 2018 at 21:52
  • Note that ctypes.POINTER(ctypes.c_char_p) is a double pointer (equivalent of char **). Is that what you're after? Commented Mar 9, 2018 at 6:52
  • According to the ctypes docs, c_char_p is char * (NUL terminated) and points to a bytes object. I also tried c_byte with no success. I just need the pointer to a byte array created with create_string_buffer and a pointer to a byte array read from file with encoding="utf-8" if a different pointer is needed for that. Commented Mar 9, 2018 at 15:44
  • Why use double* for the two integer (and same) string lengths? You could get by with c_size_t. Commented Mar 9, 2018 at 17:05

1 Answer 1

1

c_char_p is correct for both array parameters and equivalent to C's char*:

CallName.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.POINTER(ctypes.c_double)]

Use CA_no_punct.raw to view the full content of the output buffer.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, Mark. Based on your answer, I eliminated ctypes.POINTER and used ctypes.c_char_p alone, without ctypes.POINTER. Also, I needed to add this: CA_my_str = CA_my_str.encode('utf-8'), even though it was read from file with utf-8 encoding. Now it works using CallName.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.POINTER(ctypes.c_double)]. Thanks.
@RTC222 If you read the string from the file as 'rb' it will already be a byte string and it it won't need to be re-encoded. In your current code, you also need to take the length of the encoded byte string not the length of the Unicode string as the encoded string could be longer if the Unicode string has non-ASCII values in it, but reading as a byte string to begin with will also fix that.
#Mark Tolonen, Thanks for the tip. I made the change and it does as you said. No need for the extra line.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.