Retrieving a top level function address

As titled, writing a customized gl wrapper, I'm defining each function via glXGetProcAddressARB, because the header exposes from itself functions as:

typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);

However, if I define GL_GLEXT_PROTOTYPES before importing #include "/usr/include/GL/glcorearb.h" then I have also the normal functions:

#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glCullFace (GLenum mode);

For the sake of curiosity, I'd like now to compare the function address I manually retrieved via glXGetProcAddressARB with the one of glCullFace

I tried

var a = glCullFace
print(&a)

But I keep getting:

error: '&' used with non-inout argument of type 'Any'

I tried:

print(unsafeBitCast(glCullFace.self, to: UnsafeMutableRawPointer.self))

But I get:

Fatal error: Can't unsafeBitCast between types of different sizes

Which is the right way?

This will work:

let myFunc: @convention(c) (CInt, UnsafeRawPointer?, size_t) -> ssize_t = write
print(unsafeBitCast(myFunc, to: UnsafeRawPointer.self))

The key is to assign it to a @convention(c) type first.

If you don't, then the sizes don't match because the memory representation of general Swift function references (also named @convention(thick) but that's irrelevant here) is two words:

  • function pointer (1 word)
  • captured context pointer (1 word) because they can capture other variables and the pointee will store all the value of what's captured.

C functions (& "thin functions") however cannot capture and therefore can be represented easily with just one pointer. To make a type that can only use a C function use @convention(c). (Thin functions are @convention(thin) but don't use that).

2 Likes

Thanks, it works flawless

print(unsafeBitCast(glCullFace as PFNGLCULLFACEPROC, to: UnsafeRawPointer.self))

(PFNGLCULLFACEPROC has @convention(c))

1 Like