[swift-dev] C API Annotations outside of original header?

Geordie J geojay at gmail.com
Sun Jul 17 15:39:14 CDT 2016


Hi, I’m hoping to add CF_SWIFT_NAME annotations to an imported Clang module (JNI) without editing the original header file itself. Is this possible, or is there a working alternative other than creating a Swift wrapper? Maybe this is trivial but C is not my strong point.

Specifically, there are a bunch of type names in the Android JNI that I’d rather just keep „Swifty“ (the CF_SWIFT_NAME additions are my own of course, working with a copy of the original file for now):

typedef unsigned char   		jboolean; // can be 0 or 1 - is this the same as CFBoolean?
typedef signed char     		jbyte CF_SWIFT_NAME(Int8);
typedef unsigned short  		jchar CF_SWIFT_NAME(UInt8);
typedef short           		jshort CF_SWIFT_NAME(Int16);
typedef int             			jint CF_SWIFT_NAME(Int32);
typedef long long       		jlong CF_SWIFT_NAME(Int);
typedef float           			jfloat CF_SWIFT_NAME(Float);
typedef double          		jdouble CF_SWIFT_NAME(Double);


Note that there’s no good way of wrapping these in pure Swift, as far as I can see (they show up throughout the rest of the APIs). Also, it’d be great if the following was possible from outside the header. Instead of:

typedef enum jobjectRefType {
    JNIInvalidRefType = 0,
    JNILocalRefType = 1,
    JNIGlobalRefType = 2,
    JNIWeakGlobalRefType = 3
} jobjectRefType;

… to use:

typedef NS_ENUM(NSInteger, jobjectRefType) {
    JNIInvalidRefType CF_SWIFT_NAME(invalid) = 0,
    JNILocalRefType CF_SWIFT_NAME(local) = 1,
    JNIGlobalRefType CF_SWIFT_NAME(global) = 2,
    JNIWeakGlobalRefType CF_SWIFT_NAME(weakGlobal) = 3
};


The final question is whether it’s at all possible to annotate this kind of API:

struct JNINativeInterface {
    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
                        jsize);
    // and about 100 more of these ...
}

This imports into Swift as jni.DefineClass(env, string, obj, bytes, size). Attempting to put a type annotation into the header results like this:

jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, size)
        CF_SWIFT_NAME(defineClass(env:name:object:byteContents:size:));

results in a strange warning: "‚swift_name‘ attribute has invalid identifier for base name“. It is possible to just rename DefineClass to e.g. defineClass, via CF_SWIFT_NAME(defineClass); I assume this is because this is a function pointer on a struct rather than a global function.

Any help regarding the above would be much appreciated. Playing around with those changes locally has made huge improvements to the readability of Android/JNI-specific Swift code. If I can find a clean solution to this I’d like to finally clean up and upstream the SwiftJNI module I started here: https://github.com/SwiftAndroid/swift-jni <https://github.com/SwiftAndroid/swift-jni>

Thanks,
Geordie
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160717/8438da24/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 455 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160717/8438da24/attachment.sig>


More information about the swift-dev mailing list