Hello, I am going to show you how you can develop a native app for Windows* and Android* that can reuse the shared app logic in C++. This is going to be a simple hello world app for you to understand the process. I am using Android Studio installed by Intel® INDE 2015 Update 2 for building the Android UI. (You can update it to 1.2.2 without losing Intel INDE plugins) And Visual Studio 2013 for building the Windows UI and both are going to call the native C++ API that is shared between these two apps. This article assumes that you are aware of the basic process of building and emulating apps on Android Studio and Visual Studio.
Step 1:
The structure of your workspace directory should look like this.
Workspace/CoreCommon (Shared C/C++ files)
- Hello.c (has print_hello() that is called by both the apps)
- Hello.h
Workspace/CrossPlatformAndroid
Workspace/CrossPlatformWindows
Step 2:
Letz start with building the Android project in Android Studio.
New Project -> Choose the directory that you just created for Android Project
And choose Intel® INDE plugin “Blank Activity with NDK”
How does Intel® INDE help with building this app?
First of all, the process of NDK build is made very simple in Android Studio with the IDE Integration feature of Intel® INDE. The template has the boiler plate code for your simple hello-jni app that can be readily compiled. The Gradle build script that comes with the feature invokes the NDK-BUILD as part of the app compilation process and app compilation is made dependent on the success of the ndk-build. i.e, only if the C++ library is built successfully, the compilation of the rest of app is successful. You don’t have to invoke the ndk-build separately.
task ndkBuild(type: Exec) { if (Os.isFamily(Os.FAMILY_WINDOWS)) { def ndkDir = System.getenv("ANDROID_NDK_ROOT") commandLine 'cmd', '/C', "$ndkDir/ndk-build",'NDK_PROJECT_PATH=build','APP_BUILD_SCRIPT=src/main/jni/Android.mk','NDK_APPLICATION_MK=src/main/jni/Application.mk','NDK_APP_LIBS_OUT = src/main/jnilibs' } else { def ndkDir = System.getenv("NDKROOT") commandLine "$ndkDir/ndk-build",'NDK_PROJECT_PATH=build','APP_BUILD_SCRIPT=src/main/jni/Android.mk','NDK_APPLICATION_MK=src/main/jni/Application.mk','NDK_APP_LIBS_OUT = src/main/jnilibs' } } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild }
Step 3:
Now, change the jni/Android.mk file to include the files under CoreCommon to build the MyLib library. The above gradle script then builds the MyLib.so file which can be located at app/src/jnilibs
Step 4:
Now go to NativeCode.c file and make the highlighted modification. Basically, print_hello() function is called from the shared library.
If you look at src/main/java/MainActivity.java, the above jni function “getStringFromNative” is called which in turn calls from the shared library to print the hello string.
Step 5:
Build -> Rebuild Project and you will see in Gradle Build terminal (abbreviated):
:app:generateDebugSources
:app:ndkBuild
[x86] Compile : MyLib <= NativeCode.c
[x86] Compile : MyLib <= hello.c
[x86] SharedLibrary : libMyLib.so
:app:compileDebugAndroidTestNdk UP-TO-DATE
:app:compileDebugAndroidTestSources
Information:BUILD SUCCESSFUL
Step 6: Run the app in the Android Emulator.
On similar lines, letz start the Windows* App from Visual Studio 2013.
First, build the shared C++ library.
Step 1: Create an empty C++ project
Open Solution Explorer and add NativeCode.h to the Header Files and NativeCode.cpp to SourceFiles. Contents below:
NativeCode.h:
#include <Windows.h> #include "hello.h" using namespace std; #if defined(_BUILD_DLL) # define DLLAPI __declspec(dllexport) //Export when building DLL #else # define DLLAPI __declspec(dllimport) //Import when using in other project #endif #ifdef __cplusplus extern "C" { #endif DLLAPI char* DisplayHelloFromDLL(); #ifdef __cplusplus } #endif NativeCode.cpp: #include "NativeCode.h" char* DisplayHelloFromDLL() { char* str = print_hello(); return str; }
Step 2: Add hello.c from CoreCommon to the Source Files of this project and hello.h to Header Files of this project.
Right click Header Files -> Add -> Existing Item -> ../CoreCommon/hello.h
Right click Source Files -> Add -> Existing Item -> ../CoreCommon/hello.c
Remember, you may have to include the CoreCommon directory in your Project Properties:
Step 3: Right click project -> Build.
If your build is successful, you will see the dll under ..\Workspaces\CrossPlatformWindows\Debug
Your shared library is successfully built for your Windows app.
Step 4: Now, letz build the UI for the Windows App. It can be a simple text box to display the string from the hello.c file.
Right click Solution Explorer -> Add -> New Project -> Visual C#
Right Click the project and “Set as StartUp Project”
Step 5:
Open the main .cs file and make reference to the dll that was created in Step 3. Remember to include System.Runtime.InteropServices
Add a simple UI and an event handler that calls the shared CPP code to print the "Hello World" like below:
Step 6:
BUILD -> Rebuild Solution.
If your build is successful, you should see:
1>------ Rebuild All started: Project: NativeCPPLib, Configuration: Debug Win32 ------
2>------ Rebuild All started: Project: HelloCSharp, Configuration: Debug Any CPU ------
2>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.CSharp.CurrentVersion.targets(448,9): warning MSB3052: The parameter to the compiler is invalid, '/define:/clr' will be ignored.
2> HelloCSharp -> C:\INDE\Workspaces\CrossPlatformWindows\HelloCSharp\bin\Debug\HelloCSharp.exe
1> hello.c
1> NativeCode.cpp
1> Creating library C:\INDE\Workspaces\CrossPlatformWindows\Debug\NativeCPPLib.lib and object C:\INDE\Workspaces\CrossPlatformWindows\Debug\NativeCPPLib.exp
1> NativeCPP.vcxproj -> C:\INDE\Workspaces\CrossPlatformWindows\Debug\NativeCPPLib.dll
========== Rebuild All: 2 succeeded, 0 failed, 0 skipped ==========
Step 7:
Run the solution (press F5) and voila, you will see your Windows app in action!
You have successfully built your cross platform app for Windows and Android. And this is how you reuse the shared Native App Logic across different operating systems. Native App Logic is the place where many of Intel® INDE’s SDKs like Media SDK and libraries like Integrated Performance Primitives and Threading Building Blocks fit in to make your apps run in the most optimized way for the underlying architecture.
The code for this application is uploaded from the root directory level for your reference. Please post your feedback or questions below.