Android API'ler için kitaplık sarmalayıcı Android Oyun Geliştirme Kiti'nin bir parçasıdır.
Kitaplık sarmalayıcı, C dili oluşturan bir komut satırı aracıdır (KSA) sarmalayıcı kodu kullanabilirsiniz. Bunu kullanabilirsiniz manuel olarak gerek kalmadan Java API'lerini çağırmak için yerel Android uygulamalarında kod Java Yerel Arayüzü veya JNI oluşturmanız gerekir. Bu araç, geliştirmeyi kolaylaştırabilir Temel olarak C veya C++ dilinde yazılmış Android uygulamaları.
Araç, tablodaki herkese açık semboller için C kodu oluşturarak Sağladığınız Java Arşivi (JAR) dosyaları veya aracın dosyası veya her ikisi de olabilir. Araç tarafından oluşturulan kod Java'nın yerine geçmez API'ler yerine, C kodunuz ile Java arasında bir köprü görevi görür. Uygulama resminiz sarmaladığınız Java kitaplıklarının projenize dahil edilmesini gerektirir.
İndir
Kitaplık sarmalayıcı arşivini indirin ve içeriğini dizine açın tercih edebilirsiniz.
Sözdizimi
Kitaplık sarmalayıcı aracı aşağıdaki komut satırı söz dizimine sahiptir:
java -jar lw.jar \
[-i jar-file-to-be-wrapped] \
[-o output-path] \
[-c config-file] \
[-fa allow-list-file] \
[-fb block-list-file] \
[--skip_deprecated_symbols]
Parametre | Açıklama |
---|---|
-i jar-file-to-be-wrapped |
JAR dosyası oluşturun. Birden fazla JAR belirtilebilir.
örneğin: -i first_library.jar -i second_library.jar...
|
-o output-path |
Oluşturulan kodun dosya sistemi konumu. |
-c config-file |
Kitaplık sarmalayıcı yapılandırma dosyasının dosya sistemi yolu. Ayrıntılı bilgi için Yapılandırma bölümünü inceleyin. |
-fa allow-list-file |
Bir filtre dosyasına giden bir yoldur. Bu dosyada aracın sarmalayın. Ayrıntılar için Filtre bölümüne bakın. |
-fb block-list-file |
Sarmalamadan hariç tutulan semboller içeren bir filtre dosyasının yolu. Örneğin, Filtre bölümüne bakın. |
--skip_deprecated_symbols |
Sarmalayıcı aracına atlama talimatı verir @Kullanımdan kaldırıldı anlamına gelir. |
Sarmalayıcı yapılandırma dosyası
Kitaplık sarmalayıcı yapılandırması, kod oluşturma sürecidir. Dosya aşağıdaki yapıyı kullanır.
{
// An array of type-specific configs. A type config is useful when a user wants to map
// a Java type to a manually defined C type without generating the code. For example, when a developer
// has their own implementation of the "java.lang.String" class, they can tell the generator to use it
// instead of generating it.
"type_configs": [
{
// [Required] Name of a fully qualified Java type.
"java_type": "java.lang.String",
// The C type that the java_type will be mapped to.
"map_to": "MyOwnStringImplementation",
// A header file that contains the declaration of the "map_to" type.
"source_of_definition": "my_wrappers/my_own_string_implementation.h",
// Controls if a value should be passed by pointer or value.
"pass_by_value": false
}
],
// An array of package-specific configs.
"package_configs": [
{
// [Required] A name of a Java package that this section regards. A wildchar * can be used at the
// end of the package name to apply this config to all packages whose name starts with this value.
"package_name": "androidx.core.app*",
// A subdirectory relative to the root directory where the generated code will be located.
"sub_directory": "androidx_generated/",
// If true, the generated file structure reflects the package name. For example, files generated
// for the package com.google.tools will be placed in the directory com/google/tools/.
"file_location_by_package_name": true,
// A prefix added to all class names from this package.
"code_prefix": "Gen",
// A prefix added to all generated file names from this package.
"file_prefix": = "gen_"
}
],
// An array of manually defined classes for wrapping. Defining classes manually is useful when a
// jar file with desired classes are not available or a user needs to wrap just a small part of an SDK.
"custom_classes": [
{
// [Required] A fully-qualified Java class name. To define inner class, use symbol "$", for example
// "class com.example.OuterClass$InnerClass".
"class_name": "class java.util.ArrayList<T>",
// List of methods.
"methods": [
"ArrayList()", // Example of a constructor.
"boolean add(T e)", // Example of a method that takes a generic parameter.
"T get(int index)", // Example of a method that returns a generic parameter.
"int size()" // Example of parameterless method.
]
},
]
}
Dosyaları filtrele
Sarmalamayı planladığınız JAR dosyalarından bazı simgeleri hariç tutmak yararlı olabilir. Siz yapılandırmanızda simgeleri hariç tutacak bir filtre dosyası belirtebilir. Filtre dosyası her satırın kaydırılacak bir simge tanımladığı basit bir metin dosyasıdır. Dosya kullanımını filtrele şu söz dizimini kullanabilirsiniz:
java-symbol-name java-jni-type-signature
Aşağıda örnek bir filtre dosyası verilmiştir:
# Class filter
java.util.ArrayList Ljava.util.ArrayList;
# Method filter
java.util.ArrayList.lastIndexOf (Ljava.lang.Object;)I
# Field filter
android.view.KeyEvent.KEYCODE_ENTER I
Yapılandırma'ya,
-fa
parametresi kullanılmasına izin verilir, engellenen simgeler ise -fb
parametresinden sonra bir değer girin. Her iki parametre de aynı anda kullanılabilir. Her iki filtre de
bir simge, izin ver filtresi dosyasında tanımlandığında sarmalanır
ve engelleme filtresi dosyasında bulunmaz.
Örnek senaryo
ChatLibrary.jar
öğesini içeren JAR dosyasını sarmalamanız gerektiğini varsayalım.
takip etmek için:
public class ChatManager {
public static void sendMessage(int userId, String message) {...}
}
C projeniz, bu JAR için yerel sarmalayıcı oluşturmanızı gerektiriyorsa yerel Android uygulamanızı çalışma zamanında çağırmak için kullanın. Bu kodu kitaplık sarmalayıcıyı şu komutla kullanabilirsiniz:
java -jar lw.jar -i ChatLibrary.jar -o ./generated_code/
Önceki komut, dizin için C kaynak kodu oluşturur
./generated_code
Oluşturulan chat_manager.h
dosyası şuna benzer bir kod içeriyor:
Projenizdeki kitaplığı çağırmanıza olanak tanır:
#include "java/lang/string.h"
typedef struct ChatManager_ ChatManager;
void ChatManager_sendMessage(int32_t user_id, String* message);
Ayrıntılı bir örnek senaryo için Kitaplık sarmalayıcı kılavuzuna bakın.
Araç ayrıntıları
Aşağıdaki bölümlerde kitaplık sarmalayıcıların işlevi görür.
Çıkış dizini yapısı
Tüm C kaynak ve üstbilgisi dosyaları,
paket adı. Örneğin,
belirtilen JAR java.lang.Integer
, dizin için oluşturulur
./java/lang/integer.[h/cc]
.
Bu çıkış davranışını aracın configuration dosyasına göz atın.
Nesne yaşam döngüsü
Java nesneleri, C kodunda sarmalayıcı adı verilen opak işaretçiler olarak temsil edilir. Sarmalayıcı, karşılık gelen Java nesnesi için bir JNI referansını yönetir. Sarmalayıcı şu senaryolarda oluşturulabilir:
- İşlevi çağırarak mevcut bir JNI referansını sarmalayarak
MyClass_wrapJniReference(jobject jobj)
İşlev sağlanan referansın sahipliğini almaz, ancak kendi referansını oluşturur global JNI referansı. - Bir oluşturucuyu çağırmaya eşdeğer yeni bir nesne oluşturarak
Java:
MyClass_construct()
- Bir işlevden yeni bir sarmalayıcı döndürerek. Örneğin:
Score* Leaderboard_getScore(Leaderboard* instance, String* leaderboard_name)
.
Artık kullanılmayan tüm sarmalayıcıları kaldırmanız gerekir. Bunu yapmak için
destroy()
işlevi MyClass_destroy(MyClass* instance)
.
Sarmalayıcı döndüren işlevler her çağrıda kendilerine yeni bir bellek ayırır. olsa bile sarmalayıcılar aynı Java örneğini temsil eder.
Örneğin, Java yöntemi Singleton.getInstance()
her zaman
C tarafındaki eşdeğer fonksiyon, yeni bir örnek oluşturacaktır
bir sarmalayıcı içerir:
Singleton* singleton_a = Singleton_getInsance();
Singleton* singleton_b = Singleton_getInsance();
// singleton_a and singleton_b are different pointers, even though they represent the same Java instance.
Başvuruda bulunulmayan sınıfları işleme
Bir sınıf, sağlanan bir JAR'da bulunamadığında libarary sarmalayıcı bir opak bir işaretçi ve aşağıdaki yöntemleri içeren temel uygulama:
wrapJniReference()
getJniReference()
destroy()
Kod oluşturma ayrıntıları
Kitaplık sarmalayıcı, çalıştırıldığında aracı sağladığınız JAR dosyaları. Oluşturulan C kodu farklılıklar gösterebilir kodundan çıkarırım. Örneğin C, OOP gibi özellikleri desteklemez, ya da diğer Java özellikleri için de geçerlidir.
Bu durumları yansıtan, oluşturulan C kodu, C geliştiricilerinin beklediği koddur. Aşağıdaki bölümlerde yer alan örnekler; aracın Java kodundan nasıl C oluşturabileceğine ilişkin bağlam Not: Kod snippet'lerinde aşağıdaki örnekler arasında C/C++ ve Java kodu bulunmaktadır. için de geçerlidir. Bu snippet'ler yalnızca aracın her durum için kod oluşturur.
Sınıflar
Sınıflar, C'de opak işaretçiler olarak gösterilir:
C/C++
typedef struct MyClass_ MyClass;
Java
public class MyClass { ... }
Opak işaretçi örneklerine sarmalayıcı olarak başvurulur. Sarmalayıcı aracı
her sınıf için ek destek işlevleri oluşturur. Yukarıdaki örnek için
MyClass
sınıfını seçerseniz aşağıdaki işlevler oluşturulur:
// Wraps a JNI reference with MyClass. The 'jobj' must represent MyClass on the Java side.
MyClass* MyClass_wrapJniReference(jobject jobj);
// Return JNI reference associated with the 'MyClass' pointer.
jobject MyClass_getJniReference(const MyClass* object);
// Destroys the object and releases underlying JNI reference.
void MyClass_destroy(const MyClass* object);
Markalar
Genel veya varsayılan oluşturucuları olan sınıflar, özel işlevler:
C/C++
MyClass* MyClass_construct(String* data);
Java
public class MyClass {
public MyClass(String data) { ... }
}
Yöntemler
Yöntemler normal fonksiyonlar olarak temsil edilir. Bir işlevin adı
orijinal sınıf adı. Statik olmayan örnek yöntemlerini temsil eden işlevler
ilk parametre olarak, JavaScript nesnesini temsil eden yapıya
sahip olması gerekir. Bu yaklaşım this
ile benzerdir
tıklayın.
C/C++
Result* MyClass_doAction(const MyClass* my_class_instance, int32_t action_id, String* data);
int32_t MyClass_doAction(int32_t a, int32_t b);
Java
public class MyClass {
public Result doAction(int actionId, String data) { ... }
public static int doCalculations(int a, int b) { ... }
}
Özel dersler
İç sınıflar, karşılık gelen C yapısı, dış sınıfların zincirli adlarını içerir:
C/C++
typedef struct MyClass_InnerClass_ MyClass_InnerClass;
Java
public class MyClass {
public class InnerClass {...}
}
Sınıf içi yöntemler
İç sınıf yöntemleri aşağıdaki gibi temsil edilir:
C/C++
bool MyClass_InnerClass_setValue(MyClass_InnerClass* my_class_inner_class_instance, int32_t value);
Java
public class MyClass {
public class InnerClass {
public boolean setValue(int value) { ... }
}
}
Genel türler
Kitaplık sarmalayıcı genel türleri doğrudan sarmaz. Bunun yerine, yalnızca genel tür örneklendirmeler için sarmalayıcılar oluşturur.
Örneğin, API'de bir MyGeneric<T>
sınıfı mevcutsa ve iki
bu sınıfın örneklendirmeleri, örneğin MyGeneric<Integer>
ve
MyGeneric<String>
, bu iki örneklendirme için sarmalayıcılar oluşturulur. Bu
demek, MyGeneric<T>
kullanarak
yapılandırabilirsiniz. Aşağıdaki örneğe bakın:
C/C++
// result.h
typedef struct Result_Integer_ Result_Integer;
typedef struct Result_Float_ Result_Float;
Integer* Result_Integer_getResult(const Result_Integer* instance);
Float* Result_Float_getResult(const Result_Float* instance);
// data_processor.h
typedef struct DataProcessor_ DataProcessor;
Result_Integer* DataProcessor_processIntegerData(const DataProcessor* instance);
Result_Float* DataProcessor_processFloatData(constDataProcessor* instance);
Java
public class Result<T> {
public T getResult();
}
public class DataProcessor {
public Result<Integer> processIntegerData();
public Result<Float> processFloatData();
}
Arayüzleri uygulama
implementInterface()
çağrısı yaparak C arayüzü uygulayın.
geri çağırma işlevinden yararlanırız. Yalnızca arayüzler uygulanabilir
uygun şekilde sunar. sınıflar ve soyut sınıflar desteklenmez. Bkz.
şu örneği inceleyin:
C/C++
// observer.h
typedef struct Observer_ Observer;
typedef void (*Observer_onAction1Callback)();
typedef void (*Observer_onAction2Callback)(int32_t data);
Observer* Observer_implementInterface(
Observer_onAction1Callback observer_on_action1_callback,
Observer_onAction2Callback observer_on_action2_callback);
Java
public interface Observer {
void onAction1();
void onAction2(int data);
}
public class Subject {
public void registerObserver(Observer observer);
}
Kullanım örneği:
void onAction1() {
// Handle action 1
}
void onAction2(int32_t data) {
// Handle action 2
}
Observer* observer = Observer_implementInterface(onAction1, onAction2);
Subject_registerObserver(subject, observer);
Sınırlamalar
Kitaplık sarmalayıcı aracı beta sürümündedir. Aşağıdaki durumlarla karşılaşabilirsiniz: sınırlamalar:
Desteklenmeyen Java yapıları
Kitaplık sarmalayıcı beta aşağıdaki yapıları desteklemez:
Yöntemde aşırı yükleme
C dili, aynı ada sahip iki işlevin bildirilmesine izin vermez. Eğer sınıf, yöntemin aşırı yüklemesini kullandığında oluşturulan C kodu derlemez. İlgili içeriği oluşturmak için kullanılan geçici çözüm, yeterli parametre grubuna sahip tek bir yöntem kullanmaktır. Geri kalan işlevler, filtreler kullanılarak filtrelenebilir. Bu kurucular için de geçerlidir.
Şablonlu yöntemler
static final int
vestatic final String
dışındaki alanlarDiziler
Olası ad çakışmaları
Java sınıflarının C koduyla temsil edilme biçiminden dolayı,
çatışmalara neden olabilir. Örneğin, bir Foo<Bar>
sınıfı ve bir iç mekan
bir Foo
sınıfı içindeki Bar
sınıfı, C'de aynı simgeyle temsil edilir:
typedef struct Foo_Bar_ Foo_Bar;
Destek
Kitaplık sarmalayıcı ile ilgili bir sorun tespit ederseniz lütfen bize bildirin.
Hatalara göz at | Hata bildir |
---|---|
Mühendislik | bug_report |
Dokümanlar | bug_report |