Click here to Skip to main content
Click here to Skip to main content

Tagged as

(untagged)
Go to top

Calling C/C++ from java android using CLE

, 5 Mar 2012
Rate this:
Please Sign up or sign in to vote.
        There are lots of resources written in C/C++ languages. But on android platform, Java is major language. Developers have to using JNI to wrap the interface of c/c++ codes. JNI is suitable for simple case. For more complicate application, programmers have to maintain references of c++ objects

There are lots of resources written in C/C++ languages. But on android platform, Java is major language. Developers have to using JNI to wrap the interface of c/c++ codes. JNI is suitable for simple case. For more complicate application, 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 are all have reflection mechanism. We can get functions and attributes definition dynamically. But for C/C++, there has no similar mechanism. All definitions in 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 -&gt; SetAtomicFunction(Add_AtomicFunction,(void *)CAdd);    
    SRPInterface -&gt; 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();     //----save script stack
    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):

  1. Download devfiles from http://code.google.com/p/cle-for-android, and then Open Eclipse
  2. Create project for android.
  3. Add CLE jar to project as follows:


4. c++ codes

#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();     //----save script stack
    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);     //----restore script stack
}
VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
{
    void *AtomicClass,*Add_AtomicFunction,*Print_AtomicFunction;
    class ClassOfBasicSRPInterface *BasicSRPInterface;
    
    //--init star core
    BasicSRPInterface = starcore ->GetBasicInterface();    
    SRPInterface = BasicSRPInterface ->GetSRPInterface(BasicSRPInterface->QueryActiveService(NULL),"","");
    
    //---Create Atomic Class, for define function,  
    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);    
    //---Set Function Address
    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)

5. Java Codes:

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 {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //--init CLE
        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();
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

li9705

China China
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 5 Mar 2012
Article Copyright 2012 by li9705
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid