C API Annotations outside of original header?


(Geordie J) #1

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

Thanks,
Geordie


(Saleem Abdulrasool) #2

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.

AIUI, apinotes were designed specifically to address this need. You should
be able to augment the header with an apinotes set for that header.

···

On Sun, Jul 17, 2016 at 1:39 PM, Geordie J via swift-dev < swift-dev@swift.org> wrote:

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

Thanks,
Geordie

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org


(Geordie J) #3

Is it possible that apinotes only works for Objective C? The only docs I've
seen regarding them explicitly mention ObjC repeatedly

···

Saleem Abdulrasool <compnerd@compnerd.org> schrieb am Mo., 18. Juli 2016 um 00:43:

On Sun, Jul 17, 2016 at 1:39 PM, Geordie J via swift-dev < > swift-dev@swift.org> wrote:

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.

AIUI, apinotes were designed specifically to address this need. You
should be able to augment the header with an apinotes set for that header.

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

Thanks,
Geordie

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org


(Saleem Abdulrasool) #4

Is it possible that apinotes only works for Objective C? The only docs
I've seen regarding them explicitly mention ObjC repeatedly

I would find that hard to believe given that it is used for importing
libdispatch (C) into Swift.

···

On Sun, Jul 17, 2016 at 4:10 PM, Geordie Jay <geojay@gmail.com> wrote:

Saleem Abdulrasool <compnerd@compnerd.org> schrieb am Mo., 18. Juli 2016 > um 00:43:

On Sun, Jul 17, 2016 at 1:39 PM, Geordie J via swift-dev < >> swift-dev@swift.org> wrote:

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.

AIUI, apinotes were designed specifically to address this need. You
should be able to augment the header with an apinotes set for that header.

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

Thanks,
Geordie

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org


(Geordie J) #5

I see they're also used for CoreGraphics, which was the example they showed
at WWDC that put me onto the idea of using the annotations in the first
place. I'll look into it, thanks for the idea!

···

Saleem Abdulrasool <compnerd@compnerd.org> schrieb am Mo., 18. Juli 2016 um 01:23:

On Sun, Jul 17, 2016 at 4:10 PM, Geordie Jay <geojay@gmail.com> wrote:

Is it possible that apinotes only works for Objective C? The only docs
I've seen regarding them explicitly mention ObjC repeatedly

I would find that hard to believe given that it is used for importing
libdispatch (C) into Swift.

Saleem Abdulrasool <compnerd@compnerd.org> schrieb am Mo., 18. Juli 2016 >> um 00:43:

On Sun, Jul 17, 2016 at 1:39 PM, Geordie J via swift-dev < >>> swift-dev@swift.org> wrote:

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.

AIUI, apinotes were designed specifically to address this need. You
should be able to augment the header with an apinotes set for that header.

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

Thanks,
Geordie

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org

--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org