简体   繁体   中英

ctypes structure with char array empty in shared library

I have a shared C library with a struct I would like to use in my python code

struct my_struct {
  char name[64];
};

so in python I recreate it with

class MyStruct(ctypes.Structure):
  _fields_ = [
    ("name", ctypes.c_char*64)
  ]

when I check the type of MyStruct.name i get 'str', whereas I expected 'c_char_Array_64'.

s=MyStruct()
print type(s.name) # <type 'str'>

So when I set the 'name' and try to use it, C sees it as blank.

s.name="Martin"
lib=ctypes.cdll.LoadLibrary('./mylib.so')
lib.my_func(s) # prints ''

where lib is the shared C library loaded with ctypes and my_func simply prints struct->name

void my_func(struct my_struct *s){
  printf("Hello %s\n", s->name);
}

I would like to know why ctypes.Structure converts the char-array to a string and how to use it in the case specified above.

Thank you

Update & Solution

Tnanks to @CristiFati for the help on debugging this problem. I have marked his answer as correct as it is in fact the answer to the question posted. In my case the problem was that the Structs were NOT of equal lengths in the Python and C program. So to whoever stumbles upon this question in the future, be very meticulous in checking that your Structs are in fact defined equally.

You're doing something wrong, but without looking at the full code I can't say what. So I prepared a small example that works.
I'm also posting [Python 3]: ctypes - A foreign function library for Python as a reference.

dll.c :

#include <stdio.h>
#include <stdlib.h> 

#if defined(_WIN32)
#  define DLL_EXPORT __declspec(dllexport)
#else
#  define DLL_EXPORT
#endif


typedef struct Struct0_ {
    char name[64];
} Struct0;


DLL_EXPORT void test(Struct0 *ps0){
    printf("Hello %s\n", ps0->name);
}

code.py :

#!/usr/bin/env python3

import sys
import ctypes


DLL = "./dll.dll"

CharArr64 = ctypes.c_char * 64

class Struct0(ctypes.Structure):
    _fields_ = [
        ("name", CharArr64),
    ]


def main():
    dll_dll = ctypes.CDLL(DLL)
    test_func = dll_dll.test
    test_func.argtypes = [ctypes.POINTER(Struct0)]

    s0 = Struct0()
    s0.name = b"Martin"
    res = test_func(ctypes.pointer(s0))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Output :

 (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>"c:\\Install\\x86\\Microsoft\\Visual Studio Community\\2015\\vc\\vcvarsall.bat" x64 (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>dir /b code.py dll.c (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>cl /nologo /DDLL /MD dll.c /link /NOLOGO /DLL /OUT:dll.dll dll.c Creating library dll.lib and object dll.exp (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>dir /b code.py dll.c dll.dll dll.exp dll.lib dll.obj (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>"e:\\Work\\Dev\\VEnvs\\py_064_03.06.08_test0\\Scripts\\python.exe" code.py Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32 Hello Martin (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>rem Also run with Python 2.7 ... Not recommended. (py_064_03.06.08_test0) e:\\Work\\Dev\\StackOverflow\\q054089371>"e:\\Work\\Dev\\VEnvs\\py_064_02.07.15_test0\\Scripts\\python.exe" code.py Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32 Hello Martin 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM