0

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.

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

2 Comments

Can you explain the preprocessor block at the top of your answer? What does it do?
@InigoSelwood I'm on Windows using Visual Studio, and it requires explicitly exporting functions with __declspec(dllexport), but that's not supported by other compilers. It makes the code useable as as for others.

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.