O J2ObjC oferece suporte à incorporação de Objective-C em métodos nativos do Java, muito semelhante a como
O JSNI do GWT é compatível com
Incorporação de JavaScript. A principal diferença entre o embedding J2ObjC e o GWT é que o J2ObjC usa
/*-[
e ]-*/
para delinear o código do Objective-C. Essa instalação é chamada de OCNI (Objective-C)
Native Interface), para se diferenciar do JSNI do GWT.
Confira um exemplo da versão de java.lang.System
da biblioteca de emulação JRE:
public static native long currentTimeMillis() /*-[
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
]-*/;
J2ObjC copia o comentário, menos os delimitadores, para criar o corpo do método:
+ (long long int)currentTimeMillis {
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
}
Importações nativas
J2ObjC verifica o código Java que está sendo traduzido para adicionar diretivas #import para suas dependências, bem como ao importar a estrutura Foundation. No entanto, todas as importações necessárias apenas pelo código nativo precisam ser separadamente. Para adicionar importações, inclua uma seção OCNI acima da primeira classe no arquivo de origem Java e especificar as importações; Por exemplo:
package my.project;
/*-[
#import "java/lang/NullPointerException.h"
]-*/
public class Test {
native void test() /*-[
@throw [[JavaLangNullPointerException alloc] init];
]-*/;
}
A importação é necessária no exemplo acima porque o único lugar em que esse tipo é referenciado está em o código nativo.
Blocos nativos
No corpo de uma classe, o J2ObjC verifica blocos OCNI. Esses blocos são adicionados sem modificações ao arquivo traduzido na mesma posição em relação aos membros da turma traduzidos. Veja um exemplo:
/*-[
static void log(NSString *msg) {
NSLog(@"%@", msg);
}
]-*/;
Essa função C pode ser invocada por qualquer método nativo declarado após esse bloco OCNI.
Uma variante especial desse bloco OCNI insere o código no cabeçalho gerado.
do arquivo .m: /*-HEADER[...]
Como invocar métodos Java do código nativo
public native void bar(JSNIExample x, String s) /*-[
// Call instance method instanceFoo() on this
[self instanceFooWithNSString:s];
// Call instance method instanceFoo() on x
[x instanceFooWithNSString:s];
// Call static method staticFoo()
JSNIExample_staticFooWithNSString_(s);
]-*/;
Como acessar campos no código nativo
Para ler um campo de instância, use myInstanceField_
ou
self->myInstanceField_
. O sufixo à direita evita um conflito com métodos
com o mesmo nome.
Os campos que tiverem nomes reservados terão dois sublinhados. Por exemplo: um campo chamado "id" é legal em Java, mas não em Objective C. Quando traduzidas, o campo se chamará "id__". Portanto, verifique os arquivos gerados se não existem campos erros do compilador.
Para gravar em um campo de instância de objeto, use JSNIExample_set_myInstanceField(string)
Ler um campo estático: JSNIExample_get_myStaticField()
Escreva um campo estático: JSNIExample_set_myStaticField(value)
J2ObjC e GWT
Delimitadores diferentes foram escolhidos para que, na próxima versão do J2ObjC, os comentários do GWT JSNI sejam ignorados (anteriormente, os mesmos delimitadores eram usados como GWT). Isso significa que uma única fonte Java pode têm métodos nativos com implementações em Objective-C, GWT e Android (via JNI):
static native void log(String text) /*-{ // left-brace for JavaScript
console.log(text);
}-*/ /*-[ // left-bracket for Objective-C
NSLog(@"%@", text);
]-*/;
J2ObjC e Android
As implementações de métodos nativos do J2ObjC e do Android "simplesmente funcionam", porque os métodos nativos do Android são implementadas em um arquivo JNI C ou C++ separado. Todos os comentários OCNI em classes Java são removidos quando compilado por javac para Android ou qualquer outra plataforma Java.