There are lots of resources written in C/C++ languages. But on Android platform, Java is major language. Developers have to use JNI to wrap the interface of C/C++ codes. JNI is suitable for simple case. For more complicated applications, programmers have to maintain references of C++ objects to Java objects, process callback functions from C/C++ to Java, etc., which are not easy. Using CLE, these works will be done by CLE, programmers only need to focus on specific functions.
For Java calls C/C++ using CLE, method is not directly as Java calls scripts, such as lua, python, etc. Because, script languages all have reflection mechanism. We can get functions and attributes definition dynamically. But for C/C++, there is no similar mechanism. All definitions in the source code will be compiled into binary code. Therefore, we need descript functions and attributes of objects first, if CLE is used.
There are two methods to descript object’s attributes and functions.
First Method, Using Interface Functions of CLE
void *AtomicClass,*Add_AtomicFunction,*Print_AtomicFunction;
AtomicClass = SRPInterface ->CreateAtomicObjectSimple(
"TestItem","TestClass","VS_INT32 CValue",NULL,NULL);
Add_AtomicFunction = SRPInterface ->CreateAtomicFunctionSimple(
AtomicClass,"CAdd",
"VS_INT32 CAdd(VS_INT32 x,VS_INT32 y);",NULL,NULL,VS_FALSE,VS_FALSE);
Print_AtomicFunction = SRPInterface ->CreateAtomicFunctionSimple(
AtomicClass,"CPrint",
"void CPrint(VS_INT32 x,VS_INT32 y);",NULL,NULL,VS_FALSE,VS_FALSE);
Second Method, Using XML String Generates object’s Attributes and Functions
void *AtomicClass,*Add_AtomicFunction,*Print_AtomicFunction;
class ClassOfSRPSXMLInterface *SXMLInterface;
SXMLInterface = BasicSRPInterface -> GetSXMLInterface();
SXMLInterface -> LoadFromBuf(
" <?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
" <sysrootitem>\n"
" <TestItem>\n"
" <object>\n"
" <TestClass ID=\"ed51e615-e548-442e-8802-a99b2fa8fe15\">\n"
" <attribute>\n"
" <CValue Type=\"VS_INT32\" />\n"
" </attribute>\n"
" <function>\n"
" <CAdd ID=\"f402fd47-8bea-4136-b7f7-45bb7fb51b14\">\n"
" <input Name=\"x\" Type=\"VS_INT32\" />\n"
" <input Name=\"y\" Type=\"VS_INT32\" />\n"
" <output Type=\"VS_INT32\" />\n"
" </CAdd>\n"
" <CPrint ID=\"da44c24e-f20a-46e3-8d37-49c3b90c6c05\">\n"
" <input Name=\"x\" Type=\"VS_INT32\" />\n"
" <input Name=\"y\" Type=\"VS_INT32\" />\n"
" </CPrint>\n"
" </function>\n"
" </TestClass>\n"
" </object>\n"
" </TestItem>\n"
" </sysrootitem>\n"
,NULL);
SRPInterface -> XmlToSysRootItem(SXMLInterface,NULL,"",NULL,0);
AtomicClass = SRPInterface ->GetAtomicObject
(_UUIDPTR("ed51e615-e548-442e-8802-a99b2fa8fe15"));
Add_AtomicFunction = SRPInterface ->GetAtomicFunction
(_UUIDPTR("f402fd47-8bea-4136-b7f7-45bb7fb51b14"));
Print_AtomicFunction = SRPInterface ->GetAtomicFunction
(_UUIDPTR("da44c24e-f20a-46e3-8d37-49c3b90c6c05"));
After finish object’s attributes and functions, we can attach functions body address:
//---Set Function Address
SRPInterface -> SetAtomicFunction(Add_AtomicFunction,(void *)CAdd);
SRPInterface -> SetAtomicFunction(Print_AtomicFunction,(void *)CPrint);
By now, the functions and attributes can be accessed from Java.
Java Code
StarObjectClass a = Service._GetObject("TestClass")._New();
a._Call("CAdd",12,34));
Callback of C/C++ to Java
java call back function:
StarObjectClass a = Service._GetObject("TestClass")._New()._Assign(new StarObjectClass(){
public int JavaAdd(StarObjectClass self,int x,int y){
return x+y;
}
});
C Code
VS_INT32 ScriptStack;
ScriptStack = SRPInterface -> ScriptGetStack(); SRPInterface -> Print( "Function result from java %d",
SRPInterface -> ScriptCall
(Object,NULL,"JavaAdd","(ii)i)",x,y) );
SRPInterface -> ScriptSetStack(ScriptStack);
Source code ( integrate CLE with your project):
- Download devfiles from http://code.google.com/p/cle-for-android, and then Open Eclipse
- Create project for Android.
- Add CLE jar to project as follows:
C++ Code
#include "vsopenapi.h"
class ClassOfSRPInterface *SRPInterface;
struct StructOfTestClass{
VS_INT32 CValue;
};
static VS_INT32 CAdd(void *Object,VS_INT32 x,VS_INT32 y)
{
struct StructOfTestClass *TestClass;
TestClass = (struct StructOfTestClass *)Object;
TestClass -> CValue = 200;
SRPInterface -> Print("Call c function...");
return x+y;
}
static void CPrint(void *Object,VS_INT32 x,VS_INT32 y)
{
VS_INT32 ScriptStack;
ScriptStack = SRPInterface -> ScriptGetStack(); SRPInterface -> Print( "Value defined in java is %d",SRPInterface ->
ScriptGetInt(Object,"JavaValue") );
SRPInterface -> Print( "Function result from java %d",
SRPInterface -> ScriptCall(Object,NULL,"JavaAdd","(ii)i)",x,y) );
SRPInterface -> ScriptSetStack(ScriptStack); }
VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
{
void *AtomicClass,*Add_AtomicFunction,*Print_AtomicFunction;
class ClassOfBasicSRPInterface *BasicSRPInterface;
BasicSRPInterface = starcore ->GetBasicInterface();
SRPInterface = BasicSRPInterface ->GetSRPInterface
(BasicSRPInterface->QueryActiveService(NULL),"","");
AtomicClass = SRPInterface ->CreateAtomicObjectSimple
("TestItem","TestClass","VS_INT32 CValue",NULL,NULL);
Add_AtomicFunction = SRPInterface ->CreateAtomicFunctionSimple
(AtomicClass,"CAdd","VS_INT32 CAdd(VS_INT32 x,VS_INT32 y);",
NULL,NULL,VS_FALSE,VS_FALSE);
Print_AtomicFunction = SRPInterface ->CreateAtomicFunctionSimple
(AtomicClass,"CPrint","void CPrint(VS_INT32 x,VS_INT32 y);",
NULL,NULL,VS_FALSE,VS_FALSE);
SRPInterface -> SetAtomicFunction(Add_AtomicFunction,(void *)CAdd);
SRPInterface -> SetAtomicFunction(Print_AtomicFunction,(void *)CPrint);
return VS_TRUE;
}
void StarCoreService_Term(class ClassOfStarCore *starcore)
{
SRPInterface -> Release();
return;
}
Compile code into share library using NDK, the Android.mk is:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and sourcefile(s)
LOCAL_CFLAGS += -Wno-write-strings -DENV_ANDROID
LOCAL_CPPFLAGS += -Wno-write-strings -fexceptions -DENV_ANDROID
LOCAL_LDFLAGS += -Wno-write-strings -DENV_ANDROID
LOCAL_C_INCLUDES += ../../cle_files/include
#--------source file
MODULE_CXXSRCS := AddFunction.cpp
LOCAL_SRC_FILES := ${MODULE_CXXSRCS}
LOCAL_LDLIBS := ../../cle_files/libs/armeabi/libstarlib.a
LOCAL_MODULE := AddFunction
include $(BUILD_SHARED_LIBRARY)
Java Code
package com.cle.cfromjava;
import android.app.Activity;
import android.os.Bundle;
import com.srplab.www.starcore.*;
import com.srplab.netinst.*;
public class CfromjavaActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
starcore_net_inst.InstallZipFile
(this,"libstarcore.so",
"http://www.srplab.com/android/starcore_armeabi_r3.zip",
"/data/data/com.cle.cfromjava/files");
StarCoreFactoryPath.StarCoreShareLibraryPath =
"/data/data/com.cle.cfromjava/files";
StarCoreFactoryPath.StarCoreOperationPath =
"/data/data/com.cle.cfromjava/files";
StarCoreFactory starcore= StarCoreFactory.GetFactory();
StarServiceClass Service=starcore._InitSimple
("test","123",0,0);
Service._CheckPassword(false);
Service._DoFile
("","/data/data/com.cle.cfromjava/lib/libAddFunction.so","");
StarObjectClass a = Service._GetObject
("TestClass")._New()._Assign(new StarObjectClass(){
public int JavaAdd(StarObjectClass self,int x,int y){
System.out.println("Call java function...");
return x+y;
}
});
a._Set("JavaValue",100);
System.out.println(a._Call("CAdd",12,34));
System.out.println(a._Get("CValue"));
a._Call("CPrint",56,78);
starcore._ModuleExit();
}
}