Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about the C API #59

Closed
stuaxo opened this issue Jul 19, 2017 · 8 comments
Closed

Question about the C API #59

stuaxo opened this issue Jul 19, 2017 · 8 comments
Labels

Comments

@stuaxo
Copy link
Collaborator

stuaxo commented Jul 19, 2017

I had an issue with a while back CairoCFFI, which seemed to come back to how pycairo exports things from it's .so.

PycairoContext_FromContext seems to be exported on some (but not all) distros and windows.

I noticed that PyCairo changed to the capsule API from something else previously, could this have changed how the C API is exported in it's .so ?

(And so the distros where I could access PycairoContext_FromContext be using the other mechanism) ?

@lazka
Copy link
Member

lazka commented Jul 19, 2017

No idea, maybe it depends on the distro specific compiler flags? They are not needed really, so it shouldn't matter.

If you want to access them through Python it should be possible to get all the function pointers through cairo.CAPI and PyCObject_AsVoidPtr/PyCapsule_GetPointer with ctypes, but I haven't tried that.

What are you trying to do?

@lazka
Copy link
Member

lazka commented Jul 19, 2017

Something like this:

import sys
import ctypes
from ctypes import c_void_p, py_object, c_char_p

# see pycairo.h
class CAPI(ctypes.Structure):
    _fields_ = [
        ("Context_Type", py_object),
        ("Context_FromContext", ctypes.PYFUNCTYPE(py_object, c_void_p, py_object, py_object)),
    ]

def get_capi():
    import cairo

    if sys.version_info[0] == 2:
        PyCObject_AsVoidPtr = ctypes.PYFUNCTYPE(c_void_p, py_object)(
            ('PyCObject_AsVoidPtr', ctypes.pythonapi))
        ptr = PyCObject_AsVoidPtr(cairo.CAPI)
    else:
        PyCapsule_GetPointer = ctypes.PYFUNCTYPE(c_void_p, py_object, c_char_p)(
            ('PyCapsule_GetPointer', ctypes.pythonapi))
        ptr = PyCapsule_GetPointer(cairo.CAPI, b"cairo.CAPI")

    ptr = ctypes.cast(ptr, ctypes.POINTER(CAPI))
    return ptr.contents


def main():
    capi = get_capi()

    import cairocffi
    import cairo

    surface = cairocffi.ImageSurface(cairocffi.FORMAT_ARGB32, 10, 10)
    ctx = cairocffi.Context(surface)
    ptr = ctx._pointer
    cairocffi.cairo.cairo_reference(ptr)
    ptr = int(cairocffi.ffi.cast('uintptr_t', ptr))
    print(capi.Context_FromContext(ptr, capi.Context_Type, None))


main()

@lazka lazka added the needinfo label Jul 19, 2017
@lazka
Copy link
Member

lazka commented Jul 19, 2017

I've extended the example above to transfer an object from cairocffi to pycairo.

@stuaxo
Copy link
Collaborator Author

stuaxo commented Jul 19, 2017

Do you know where the distro specific flags can be found ?

Then I can try and dig out my old tickets on this and remember what was happening on which distros :)

@lazka
Copy link
Member

lazka commented Jul 19, 2017

No idea. The symbols aren't public API, so you shouldn't use them.

@stuaxo
Copy link
Collaborator Author

stuaxo commented Jul 19, 2017

Indeed it is the converting to and from raw Cairo contexts for interoperability with cairocffi.

Cairocffi has a util.py with methods for this, but they use ctypes to get fields, it seems like a issue enough operation to support from our end.

In shoebot we ship an older version of this:
https://github.com/shoebot/shoebot/blob/master/shoebot/cairocffi_util.py

It is fine in Debian and Ubuntu, but not available on Fedora and Windows for a while now.

@lazka
Copy link
Member

lazka commented Jul 19, 2017

Indeed it is the converting to and from raw Cairo contexts for interoperability with cairocffi.

Cairocffi has a util.py with methods for this, but they use ctypes to get fields, it seems like a issue enough operation to support from our end.

By "our end" you mean pycairo? If yes, what's the use case?

Anyway, this should work for you hopefully: https://bpaste.net/show/fba9c849a004

@lazka
Copy link
Member

lazka commented Jul 21, 2017

The reason I'm asking is because I see the gain if you have an older pycairo and want to use some newer functions with cairocffi. But adding something like this to pycairo wont help those being stuck on older versions.

If there is anything unclear/missing etc. feel free to post here or open a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants