Home > Software design >  __init__ from ctypes constructor
__init__ from ctypes constructor

Time:05-11

I have a C struct and a constructor

typedef struct {
    uint32_t index;
    int32_t line;
    int16_t column;
} Position;

Position positionCreate() {
    Position position;
    position.index = 0;
    position.line = -1;
    position.column = -1;
    return position;
}

That has a Python class equivalent

from ctypes import *


library = cdll.LoadLibrary('./libposition.so')


class Position(Structure):

    _fields_ = [
        ('index', c_uint32),
        ('line', c_int32),
        ('column', c_int16),
    ]

When I initialize the class "manually":

constructor = library.positionCreate
constructor.restype = Position
position = constructor()
print(position.index, position.line, position.column)

I get the desired output:

0, -1, -1

But I want to use this constructor:

class Position(Structure):

    _fields_ = [
        ('index', c_uint32),
        ('line', c_int32),
        ('column', c_int16),
    ]

    def __init__(self):

        # Or words to this effect
        self = library.positionCreate()

And when I try this:

position = Position()
print(position.index, position.line, position.column)

I no longer get the right output:

0, 0, 0

I think my syntax of self = positionCreate() is wrong, but I don't know what would be right.

CodePudding user response:

self can't be assigned like that. What you need is __new__, which can return an instance of the class like you want:

test.c

#include <stdint.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

typedef struct {
    uint32_t index;
    int32_t line;
    int16_t column;
} Position;

API Position positionCreate() {
    Position position;
    position.index = 0;
    position.line = -1;
    position.column = -1;
    return position;
}

test.py

from ctypes import *

class Position(Structure):

    _fields_ = [('index', c_uint32),
                ('line', c_int32),
                ('column', c_int16)]

    def __new__(cls):
        return dll.positionCreate()

dll = CDLL('./test')
dll.positionCreate.argtypes = ()
dll.positionCreate.restype = Position

position = Position()
print(position.index, position.line, position.column)

Output:

0 -1 -1
  • Related