Swift: Unable to cast function pointer to (void*) for use in C-style third party library - c

How do I cast a function pointer in Swift to a (void*) for use in a third party C-style library?
I am programming an acquisition card that requires setting up an interrupt callback using a C-style function provided by a third party library. That particular function, which must be called to set up the callback, takes a (void*) argument for the callback. In C, this works:
// somefile.c
int PHX_StreamRead( tHandle, etAcq, void*);
PHX_StreamRead(handle, PHX_START, (void*)&phxvptrs_callback);
static void phxvptrs_callback(tHandle h, ui32 mask, void *p) {
//... stuff
}
But in Swift, I am unable to call PHX_StreamRead() using the function pointer phxvptrs_callback, because I get a compilation error (wrong pointer type):
// file.swift
PHX_StreamRead(handle, PHX_START, &phxvptrs_callback) // Does not compile
// Error: "Cannot pass immutable value as inout argument: phxvptrs_callback is a function"
However, (surprisingly to me at least), all my attempts to cast that pointer to anything that looks like an UnsafeRawPointer failed:
// attempts.swift
typealias callbackFctType = ((tHandle, ui32, UnsafeMutableRawPointer) -> Void)
let p1 = UnsafeRawPointer(&phxvptrs_callback) // does not compile
// Error: "Cannot pass immutable value as inout argument: phxvptrs_callback is a function"
let p2 = UnsafePointer<callbackFctType>(&phxvptrs_callback) // Similar error
I figured out a workaround (below) but I would like to understand why these casts are refusing to compile. I assumed pretty much anything could be cast to UnsafeRawPointer.
My workaround has been to create a small C file with the callback definition and a wrapper function MyPHX_StreamRead_START_WithCallBack() that just calls PHX_StreamRead() with the proper accepted C syntax:
// file.c
static void phxvptrs_callback(tHandle h, ui32 mask, void *p) {
//... stuff
}
int MyPHX_StreamRead_START_WithCallBack(tHandle handle) {
return PHX_StreamRead(handle, PHX_START, &phxvptrs_callback);
}
Of course, calling that wrapper from Swift is not an issue and solves my problem but I find this solution "Unswift".

As far as I know, the only way to convert function pointer types in Swift is using unsafeBitCast.
Try something like this:
PHX_StreamRead(handle, PHX_START, unsafeBitCast(phxvptrs_callback, to: UnsafeMutableRawPointer.self))
EDIT
If you get "fatal error: can't unsafeBitCast between types of different sizes", Swift may not be treating phxvptrs_callback as a C-function (#convention(c) closure). In such cases, a little more code needed:
typealias callbackFctType = #convention(c) (tHandle, ui32, UnsafeMutableRawPointer?)->Void
let callbackWrapper: callbackFctType = phxvptrs_callback
PHX_StreamRead(handle, PHX_START, unsafeBitCast(callbackWrapper, to: UnsafeMutableRawPointer.self))
or this would compile and work as expected:
typealias callbackFctType = #convention(c) (tHandle, ui32, UnsafeMutableRawPointer?)->Void
PHX_StreamRead(handle, PHX_START, unsafeBitCast(phxvptrs_callback as callbackFctType, to: UnsafeMutableRawPointer.self))
EDIT2
To write a callback in Swift, you can write something like this:
typealias callbackFctType = #convention(c) (tHandle, ui32, UnsafeMutableRawPointer?)->Void
let myCallback: callbackFctType = {handle, mask, p in
//This closure cannot capture the context of its surrounding scope.
//(Which means this closure cannot use `self` even when in a class.)
//...
}
PHX_StreamRead(handle, PHX_START, unsafeBitCast(myCallback, to: UnsafeMutableRawPointer.self))

Related

how to call flutter function in C [duplicate]

Hello I am using dart:ffi to build an interface with my native c/c++ library.
and I needed a way to get a callback from c to dart as an example in sqlite:
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
the third parameter in sqlite3_exec is function pointer to a callback.
so if I called this function in dart using ffi I need to pass a function pointer: and in dart:ffi Pointer class there is a function named fromFunction witch accepts a dart static function and an exceptionalReturn; but just by calling this function to get the function pointer of a dart managed function: a (sigterm) is raised and the dart code no long work in the process.
So My Question: Is there any way to get a native callback in dart, as in Python, c#, ..
Extra:
Is there any way to include dartino in a flutter project, since this ForeignDartFunction covers what I need.
I got an example to work. Hopefully you can adapt this to your case.
Example C function
EXTERNC int32_t foo(
int32_t bar,
int32_t (*callback)(void*, int32_t)
) {
return callback(nullptr, bar);
}
Dart code
First the typedefs. We need two for the native function foo and one for the Dart callback.
typedef example_foo = Int32 Function(
Int32 bar, Pointer<NativeFunction<example_callback>>);
typedef ExampleFoo = int Function(
int bar, Pointer<NativeFunction<example_callback>>);
typedef example_callback = Int32 Function(Pointer<Void>, Int32);
and the code for the callback
static int callback(Pointer<Void> ptr, int i) {
print('in callback i=$i');
return i + 1;
}
and the lookup
ExampleFoo nativeFoo =
nativeLib.lookup<NativeFunction<example_foo>>('foo').asFunction();
and, finally, use it like this:
int foo(int i) {
return nativeFoo(
i,
Pointer.fromFunction<example_callback>(callback, except),
);
}
as expected, foo(123) prints flutter: in callback i=123 and returns 124

What is the best way to call into Swift from C?

Calling into C from Swift is pretty simple, however I'm looking into making a bi-directional wrapper in C, so my C has to call Swift functions.
Right now, I can do this by declaring function pointers in C, and having my C functions call them after the Swift side has set them up to call code in Swift.
My C header file:
typedef void (*callback_t)(void);
void callBackIntoSwift( callback_t cb );
My C implementation file:
#include "stuff.h"
#include <stdio.h>
void callBackIntoSwift( callback_t cb )
{
printf( "Will call back into Swift\n" );
cb();
printf( "Did call back into Swift\n" );
}
After including my C header file in the bridging header, I can do the following on the Swift side:
let cb: callback_t = {
someKindOfSwiftFunction()
}
callBackIntoSwift( cb )
Or even:
callBackIntoSwift {
someKindOfSwiftFunction()
}
Is there a better way to do this, where function pointers and callbacks are not needed? I'd like to let the C-side call someKindOfSwiftFunction directly … but when I try to apply #convention (c) to function declarations I get the message that the attribute can only be applied to types, and not declarations.
Any ideas or codebases in e.g. Github I can take a look at?
According to Joe Groff:
There’s no official way yet. Aside from name mangling, Swift functions use a different calling convention from C. Unofficially, if you’re willing to deal with more than the usual amount of code breakage and compiler bugs, there’s an unofficial attribute #_cdecl that does this:
#_cdecl("mymodule_foo")
func foo(x: Int) -> Int {
return x * 2
}
which you can then call from C:
#include <stdint.h>
intptr_t mymodule_foo(intptr_t);
intptr_t invoke_foo(intptr_t x) {
return mymodule_foo(x);
}
You can do something like this:
FileSwift.swift
public class SwiftTest: NSObject {
#objc public static func testMethod() {
print("Test")
}
}
FileSwiftWrapper.h
void SwiftFunctionWrapper();
FileSwiftWrapper.m
#import "ProductModuleName-Swift.h"
void SwiftFunctionWrapper() {
[SwiftTest testMethod];
}
Passing values between C and Swift
In C
extern char *mySwiftFunction(char *valuefromc);
int checkSwiftFuncation(void )
{
char *retval = mySwiftFunction("samplevalue");
printf("value %s\n",retval);
return 0;
}
In Swift
#_silgen_name("mySwiftFunction") // vital for the function being visible from C
func mySwiftFunction(valuefromc: UnsafePointer<Int8>) -> UnsafeMutablePointer<Int8>
{
let value = String(cString: valuefromc, encoding: .utf8)
print ("mySwiftFUnction called in Swift with \(value!)")
let retmsg = "return message"
return retmsg.charpointer
}
extension String {
var charpointer: UnsafeMutablePointer<Int8> {
return UnsafeMutablePointer(mutating: (self as NSString).utf8String!)
}}

Function callback from C to Swift

I have this C function that simply calls back another function passed as a parameter
void call_my_function(void (*callback_function)())
{
callback_function();
}
This is C test code:
void func_to_call() // a simple test function passed in as a callback
{
printf("function correctly called");
}
void test() // entry point
{
void (*foo)();
foo = &func_to_call;
call_my_function(foo); // pass the address of "func_to_call()" to "call_my_function()"
}
Essentially, from test(), I call call_my_function() passing in the address of func_to_call(), and then call_my_function() calls back func_to_call().
From swift I see correctly the functions test() and func_to_call(), but it seems that
void call_my_function(void (*callback_function)())
is not recognized (use of unresolved identifier)
If I remove the parameter void (*callback_function)() then the function is recognized again.
What can I do to pass a Swift function address to C and have it called back? Is it possible?
Thanks
Apple confirmed me, on the dev forum, that it is not supported now, and requested me to fill a new request on the bugreporter.
Moreover, I give to the readers another detail:
It seems that in the compiled binary the symbols for all swift functions are already available and bridged to be accessible from C (even in a swift-only app)
I made an app called FunctionTest, iPhone App with this function in a swift file
func thisIsATestFunction()
{
println("test")
}
compiled, and then from Terminal:
nc /Users/xxx/Library/Developer/Xcode/DerivedData/FunctionTest-hhrbtzsuyrdoftfnbakosvenaiak/Build/Products/Debug-iphonesimulator/FunctionTest.app/FunctionTest
U _NSStringFromClass
U _OBJC_CLASS_$_NSString
U _OBJC_CLASS_$_UIResponder
U _OBJC_CLASS_$_UIViewController
U _OBJC_CLASS_$_UIWindow
000088c8 S _OBJC_CLASS_$__TtC12FunctionTest11AppDelegate
00008888 S _OBJC_CLASS_$__TtC12FunctionTest14ViewController
.........
.........
00003840 T __TF12FunctionTest19thisIsATestFunctionFT_T_ <--- this is my test function
Calling from c the address 00003840 executed the function
void (* func)() = 0x00003840;
func(); // the swift function is executed
So I think that this is already work-in-progress...hoping that they will implement this functionality in the next releases :-)

Pass delegates to external C functions in D

How do I pass a delegate to an external C function taking a function pointer, in D?
Let me cross post what I said on the newsgroup:
How do I pass a delegate to an external C function taking a
function pointer?
You can't do it directly in general, unless you can modify the C
function, then you can hack around it, but a delegate and a
regular function pointer are pretty different animals.
But perhaps you can magic hack it. Observe:
// a C function that needs a plain function
extern(C) void test(void function() f) {
// pretend this is implemented in C
f();
}
// just create a random delegate
void delegate() foo(int a) {
return { import std.stdio; writeln(a); };
}
// what we want to work
void main() {
auto dg = foo(10);
dg(); // works
//test(dg); // won't work
test(bindDelegate(dg)); // we want this
}
// transform delegate into pointer..
import std.traits;
auto bindDelegate(T, string file = __FILE__, size_t line = __LINE__)(T t) if(isDelegate!T) {
static T dg;
dg = t;
extern(C)
static ReturnType!T func(ParameterTypeTuple!T args) {
return dg(args);
}
return &func;
}
What bindDelegate does is create a special static variable and
function for that specific call. It is as if we wrote a separate
function and global to hold it.
The __FILE__, __LINE__ things are a filthy hack to make it
instantiate a separate variable+function pair for different
lines so the global variable holding the delegate won't be so
easily overwritten.

Call Go functions from C

I am trying to create a static object written in Go to interface with a C program (say, a kernel module or something).
I have found documentation on calling C functions from Go, but I haven't found much on how to go the other way. What I've found is that it's possible, but complicated.
Here is what I found:
Blog post about callbacks between C and Go
Cgo documentation
Golang mailing list post
Does anyone have experience with this? In short, I'm trying to create a PAM module written entirely in Go.
You can call the Go code from C. It is a confusing proposition, though.
The process is outlined in the blog post you linked to. But I can see how that isn't very helpful. Here is a short snippet without any unnecessary bits. It should make things a little clearer.
package foo
// extern int goCallbackHandler(int, int);
//
// static int doAdd(int a, int b) {
// return goCallbackHandler(a, b);
// }
import "C"
//export goCallbackHandler
func goCallbackHandler(a, b C.int) C.int {
return a + b
}
// This is the public function, callable from outside this package.
// It forwards the parameters to C.doAdd(), which in turn forwards
// them back to goCallbackHandler(). This one performs the addition
// and yields the result.
func MyAdd(a, b int) int {
return int( C.doAdd( C.int(a), C.int(b)) )
}
The order in which everything is called is as follows:
foo.MyAdd(a, b) ->
C.doAdd(a, b) ->
C.goCallbackHandler(a, b) ->
foo.goCallbackHandler(a, b)
The key to remember here is that a callback function must be marked with the //export comment on the Go side and as extern on the C side. This means that any callback you wish to use, must be defined inside your package.
In order to allow a user of your package to supply a custom callback function, we use the exact same approach as above, but we supply the user's custom handler (which is just a regular Go function) as a parameter that is passed onto the C side as void*. It is then received by the callbackhandler in our package and called.
Let's use a more advanced example I am currently working with. In this case, we have a C function that performs a pretty heavy task: It reads a list of files from a USB device. This can take a while, so we want our app to be notified of its progress. We can do this by passing in a function pointer that we defined in our program. It simply displays some progress info to the user whenever it gets called. Since it has a well known signature, we can assign it its own type:
type ProgressHandler func(current, total uint64, userdata interface{}) int
This handler takes some progress info (current number of files received and total number of files) along with an interface{} value which can hold anything the user needs it to hold.
Now we need to write the C and Go plumbing to allow us to use this handler. Luckily the C function I wish to call from the library allows us to pass in a userdata struct of type void*. This means it can hold whatever we want it to hold, no questions asked and we will get it back into the Go world as-is. To make all this work, we do not call the library function from Go directly, but we create a C wrapper for it which we will name goGetFiles(). It is this wrapper that actually supplies our Go callback to the C library, along with a userdata object.
package foo
// #include <somelib.h>
// extern int goProgressCB(uint64_t current, uint64_t total, void* userdata);
//
// static int goGetFiles(some_t* handle, void* userdata) {
// return somelib_get_files(handle, goProgressCB, userdata);
// }
import "C"
import "unsafe"
Note that the goGetFiles() function does not take any function pointers for callbacks as parameters. Instead, the callback that our user has supplied is packed in a custom struct that holds both that handler and the user's own userdata value. We pass this into goGetFiles() as the userdata parameter.
// This defines the signature of our user's progress handler,
type ProgressHandler func(current, total uint64, userdata interface{}) int
// This is an internal type which will pack the users callback function and userdata.
// It is an instance of this type that we will actually be sending to the C code.
type progressRequest struct {
f ProgressHandler // The user's function pointer
d interface{} // The user's userdata.
}
//export goProgressCB
func goProgressCB(current, total C.uint64_t, userdata unsafe.Pointer) C.int {
// This is the function called from the C world by our expensive
// C.somelib_get_files() function. The userdata value contains an instance
// of *progressRequest, We unpack it and use it's values to call the
// actual function that our user supplied.
req := (*progressRequest)(userdata)
// Call req.f with our parameters and the user's own userdata value.
return C.int( req.f( uint64(current), uint64(total), req.d ) )
}
// This is our public function, which is called by the user and
// takes a handle to something our C lib needs, a function pointer
// and optionally some user defined data structure. Whatever it may be.
func GetFiles(h *Handle, pf ProgressFunc, userdata interface{}) int {
// Instead of calling the external C library directly, we call our C wrapper.
// We pass it the handle and an instance of progressRequest.
req := unsafe.Pointer(&progressequest{ pf, userdata })
return int(C.goGetFiles( (*C.some_t)(h), req ))
}
That's it for our C bindings. The user's code is now very straight forward:
package main
import (
"foo"
"fmt"
)
func main() {
handle := SomeInitStuff()
// We call GetFiles. Pass it our progress handler and some
// arbitrary userdata (could just as well be nil).
ret := foo.GetFiles( handle, myProgress, "Callbacks rock!" )
....
}
// This is our progress handler. Do something useful like display.
// progress percentage.
func myProgress(current, total uint64, userdata interface{}) int {
fc := float64(current)
ft := float64(total) * 0.01
// print how far along we are.
// eg: 500 / 1000 (50.00%)
// For good measure, prefix it with our userdata value, which
// we supplied as "Callbacks rock!".
fmt.Printf("%s: %d / %d (%3.2f%%)\n", userdata.(string), current, total, fc / ft)
return 0
}
This all looks a lot more complicated than it is. The call order has not changed as opposed to our previous example, but we get two extra calls at the end of the chain:
The order is as follows:
foo.GetFiles(....) ->
C.goGetFiles(...) ->
C.somelib_get_files(..) ->
C.goProgressCB(...) ->
foo.goProgressCB(...) ->
main.myProgress(...)
It is not a confusing proposition if you use gccgo. This works here:
foo.go
package main
func Add(a, b int) int {
return a + b
}
bar.c
#include <stdio.h>
extern int go_add(int, int) __asm__ ("example.main.Add");
int main() {
int x = go_add(2, 3);
printf("Result: %d\n", x);
}
Makefile
all: main
main: foo.o bar.c
gcc foo.o bar.c -o main
foo.o: foo.go
gccgo -c foo.go -o foo.o -fgo-prefix=example
clean:
rm -f main *.o
The answer has changed with the release of Go 1.5
This SO question that I asked some time ago addresses the issue again in light of the 1.5 added capabilities
Using Go code in an existing C project
As far as I am concerned it isn't possible:
Note: you can't define any C functions in preamble if you're using
exports.
source: https://github.com/golang/go/wiki/cgo

Resources