What is the best way to call into Swift from C? - 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!)
}}

Related

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

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))

Calling Swift code in a C testing suite

I am currently working on a library in Swift that has a version already written in C. As the version in C already has a large testing suite, I would like to just run the Swift code through the C tests.
Is it possible to call Swift in C?
To call Swift from C one can wrap Swift code in Objective-C functions callable from C. A trivial contrived example follows.
Swift code:
import Foundation
#objc public class ClassSwift : NSObject {
public func addIntegers(int1:Int32, int2:Int32) -> Int32 {
return int1 + int2;
}
}
Objective-C wrapper:
// Mixed 1a is the name of my sample target
// You can see the name of your Swift header in
// Objective-C Generated Interface Header Name under Build Settings.
#import "Mixed_1a-Swift.h"
// This function is callable from C, even though it calls Swift code!
int addIntsC(int i1, int i2)
{
ClassSwift * cs = [[ClassSwift alloc] init];
return [cs addIntegersWithInt1:i1 int2:i2];
}
And, finally, here's the C code:
#include <stdio.h>
int addIntsC(int, int);
int main(int argc, const char * argv[]) {
int result = addIntsC(3, 7);
if (result == 10) puts("Test passed!");
else puts("Failed... :(");
return 0;
}

C is there a workaround to allow dynamic function calls?

I have read that C does not support dynamic function calls. My program has an ever growing number of test cases implemented as separate functions like -
int testcase1(void);
int testcase2(void);
int testcase3(void);
Each time I add a new test case, I also have have to add the call to my main function like -
int main(int argc, char **argv){
assert(!testcase1());
assert(!testcase2());
assert(!testcase3());
}
I would prefer to call something like assert(!testcase*()) where * matches any string which resolves to a valid function name in my program.
Can you think of a more convenient solution?
If you all your testcases have same signature then you can use an array of function pointers:
void (*func[])() = { testcase1, testcase2 };
for (size_t i = 0; i < sizeof(func)/sizeof(func[0]); i++) {
assert(!func[i]());
}
The best solution is likely to write a few extra lines of code when you add new test cases - it really isn't a big issue. I would recommend something along the lines of the function pointer array, as suggested in another answer.
However, just to show that everything is possible in C if you throw ugly macros at the problem, here is a not recommended alternative:
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#define TEST_CASES \ // list of "x macros"
X(testcase1) \
X(testcase2) \
X(testcase3)
#define X(func) bool func (void); // declare function prototypes
TEST_CASES
#undef X
bool (*const test_cases[])(void) = // array of read-only function pointers
{
#define X(func) &func, // point at each function
TEST_CASES
#undef X
};
int main (void)
{
for(size_t i=0; i<sizeof(test_cases)/sizeof(test_cases[0]); i++)
{
assert(test_cases[i]());
}
}
bool testcase1 (void) { puts(__func__); return true; }
bool testcase2 (void) { puts(__func__); return true; }
bool testcase3 (void) { puts(__func__); return false; }
Output:
testcase1
testcase2
testcase3
Assertion failed!
For each new test case, you would only have to write a function definition and then add it to the "x macro" list TEST_CASES. However, you need very good reasons to introduce ugly tricks like these in production code!
You can use function pointers. Read also about closures (but C99 or C11 don't have them) and callbacks.
Many operating systems provide dynamic loading. On POSIX operating systems (such as Linux or MacOSX) you can get a function pointer (actually an address) from its name in some library (or in the program executable) using dlopen & dlsym. Other operating systems may provide similar functionalities.
At last, you should consider having your testing main function be generated by some script (or some program emitting C code), using metaprogramming techniques. So you would write something which generates the C code of your testing main having a long sequence of assert, and improve your build procedure (e.g. your Makefile if using make) to run appropriately that specialized C code generator. Details are of course specific to your code. You might add some conventions (e.g. add some special comment to be parsed by your test generator, etc...).
I decided to follow #Nominal Animal and #Basile Starynkevitch's approach. In mymainprog.c, I added -
int runtests(void){
void *testh;
int (*testp)(void);
char *dlmsg;
int rc;
char funcname[8];
int testnum;
testh = dlopen("libsmtests.so", RTLD_LAZY);
if (!testh){
printf("%s\n", dlerror());
return 1;
}
dlerror();
for (testnum =1; testnum < 1000; testnum++){
sprintf(funcname,"testcase%d", testnum);
*(void **) (&testp) = dlsym(testh, funcname);
dlmsg = dlerror();
if (dlmsg == NULL) {
rc = (*testp)();
printf("%s called, rc=%d\n", funcname, rc);
}
}
dlclose(testh);
return 0;
}
I add my testcases to a separate file (testcases.c) like this -
int testcase1(void){
return [some testcase expression]
}
int testcase2(void){
return [another testcase expression]
}
and then compile it as a shared library with position-independant code (-fPIC) to libsmtests.so. The advantage is slightly less typing since I don't need to code a call to testNNNN() after adding the implementation of a new functionint testcaseNNN(void) to testcases.c

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.

Mixing C functions in an Objective-C class

I am writing an Objective-C class but it uses an API written in C. This is mostly fine as mixing C calls with Objective-C calls causes few problems.
However one of the API call requires a call back method (example):
success = CFHostSetClient(host, MyCFHostClientCallBack, &context);
Where MyCFHostClientCallBack is a C function defined like this:
static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
Can/How do I call an Objective-C method in place of this?
Can/Should I mix C functions with my Objective-C calls?
How do I mix C functions with Objective-C methods?
Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)
Download the Zip file (09_MySQLiteTableView.zip)
C functions need to be declared outside of the #implementation in an Objective-C (.m) file.
int MyCFunction(int num, void *data)
{
//code here...
}
#implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
#end
Because the C function is outside of the #implementation it cannot call methods like
[self doSomething]
and has no access to ivars.
This can be worked around as long as the call-back function takes a userInfo or context type parameter, normally of type void*. This can be used to send any Objective-C object to the C function.
As in the sample code, this can be manipulated with normal Objective-C operations.
In addition please read this answer: Mixing C functions in an Objective-C class
To call Objective-C code from a C callback I would use something like:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
#implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
Can/How do I call an Objective-C method in place of this?
You cannot.
Can/Should I mix C function in with my Objective-C call?
Yes. Write a C function and use that as the callback to the CF function.
How do I mix C function with Objective-C methods?
You can set self as the info pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info pointer back to id:
MyClass *self = (id)info;
You can then send self messages. You still can't directly access instance variables, though, since a C function is outside of the #implementation section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside #implementation, but in the same file with it, generally right above it.)
What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.
.m call function inside .c:
CrifanLib.h
#ifndef CrifanLib_h
#define CrifanLib_h
#include <stdio.h>
void fileModeToStr(mode_t mode, char * modeStrBuf);
#endif /* CrifanLib_h */
CrifanLib.c
#include "CrifanLib.h"
#include <stdbool.h>
void fileModeToStr(mode_t mode, char * modeStrBuf) {
// buf must have at least 10 bytes
const char chars[] = "rwxrwxrwx";
for (size_t i = 0; i < 9; i++) {
// buf[i] = (mode & (1 << (8-i))) ? chars[i] : '-';
bool hasSetCurBit = mode & (1 << (8-i));
modeStrBuf[i] = hasSetCurBit ? chars[i] : '-';
}
modeStrBuf[9] = '\0';
}
called by Objective-C's .m:
#include “CrifanLib.h"
#interface JailbreakDetectionViewController ()
#end
#implementation JailbreakDetectionViewController
…
char* statToStr(struct stat* statInfo){
char stModeStr[10];
fileModeToStr(statInfo->st_mode, stModeStr);
...
}
...
done.

Resources