guys. I am writing an iOS app in swift, and I need to call some C++ lib. So I've build a simple example on how to bridge between C++ and Swift, and test on an iTouch. I wrapped the C++ interface with extern C. But I can't read the file when I call C++ function. Here is the code.
When I click the button on the iOS device, it needs to call the myFun():
main.swift
@IBAction func button(sender: AnyObject) {
myFun()
}
myFun() is my C++ function, which just reads a local file("hi.c").
DlibFun.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "DlibFun.h"
#include <unistd.h>
void myFun(){
char* path = (char*)"/hi.c";
FILE* f = fopen(path, "r");
if(f != NULL){
printf("open it\n");
fclose (f);
}else{
printf("FAIL\n");
}
}
Wrapper the C++ code in C
DlibFun.h
#ifdef __cplusplus
extern "C" {
#endif
int myFun();
#ifdef __cplusplus
}
#endif
photo-Bridging-Header.h
#include "DlibFun.h"
The result is that every time it prints out "FAIL". And any one give me any hint? I have tried the different path, but none of them are correct. Is it possible that my path is wrong? or there is any thicky thing that I don't know?
As you said, the code in the question is a simple example. I don't think the problem you are asking about, namely the fact that "FAIL" is output, is related to the real difficulties of bridging between C++ and Swift. The C++ function is called correctly, but the file can't be opened, most likely because it isn't there or isn't readable. In fact, I reproduced your example in Xcode, and got the output "open it" as long as the file was available; otherwise it would be "FAIL," as in your case.
Because DlibFun.cpp includes DlibFun.h, where myFun() is declared extern "C", the C++ compiler will compile myFun() to have C linkage, meaning it can be called from C and Swift. When Swift sees myFun() through the bridging header, it just treats it as a C function and calls it as such.
In a real-world situation, myFun() would be implemented in some C++ library and compiled using a C++ compiler, giving it C++ linkage, so just creating a header in Xcode, declaring myFun() extern "C", and then including the header in the bridge won't help. The build will fail with a link error.
To call the C++ library function myFun() you can write a wrapper as follows:
///////////////////
// File DlibFunW.h:
#ifndef DlibFunW_h
#define DlibFunW_h
// Because this is a C file for use by Swift code, via
// the bridge header, we don't need #ifdef __cplusplus.
// And because myFunW() was marked extern "C" in our C++
// wrapper, it's just a C function callable from Swift.
void myFunW();
#endif /* DlibFunW_h */
////////////////////
// File DlibFun.cpp:
#include "DlibFun.h"
// This file is C++ because it calls myFun(), which is
// a function with C++ linkage.
// This code is visible only to the C++ compiler, so
// we don't need #ifdef __cplusplus
extern "C" void myFunW() { myFun(); }
Now we don't need extern "C" in DlibFun.h, since myFun() has C++ linkage, as a real-world C++ library function would. The bridging header is now just
#include "DlibFunW.h"
and Swift calls myFunW()
instead of myFun()
.
Of course, this is a very simple example dealing only with the C vs. C++ linkage problem. A real-world C++ function would take parameters and return values, often of pointer, struct, and class types, and dealing with those is a completely different can of worms. Here on StackOverflow you'll find plenty of info on that. Some questions I'd recommend:
Swift converts C's uint64_t different than it uses its own UInt64 type
How do I get a specific bit from an Integer in Swift?
Converting inout values to UnsafeMutablePointer<Unmanaged<TYPE>?>
Is it possible to convert a Swift class into C void* pointer?
Can I mix Swift with C++? Like the Objective - C .mm files
Hope you find useful info there, all the best!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.