[源码下载]


不可或缺 Windows Native (25) - C++: windows app native, android app native, ios app native



作者:webabcd


介绍
不可或缺 Windows Native之 C++

  • windows app native
  • android app native
  • ios app native



示例
一、演示windows app native 开发
1、native 层
CppCx.h

#pragma once #include <string>using namespace std;namespace NativeDll{    class CppCx    {    public:        string Hello(string name);    };}

CppCx.cpp

/* * 演示 C#, C++/CX, C/C++ 间的通信 * * 本例是 C/C++ 部分 */#include "pch.h" #include "CppCx.h" #include "DemoCx.h"using namespace NativeDll;string CppCx::Hello(string name){    // C/C++ 通过 C++/CX 调用 C#    if (DemoCx::GlobalCallback != nullptr)        DemoCx::GlobalCallback->Cx2Cs("c/c++ to c++/cx to cs");    return "hello: " + name;}


2、C++/CX 层
DemoCx.h

#pragma once #include "ICallback.h"using namespace Platform;namespace NativeDll {    // ref class 可被输出到元数据(winmd - Windows Metadata),以便其他托管程序调用    public ref class DemoCx sealed     {    public:        // 用“^”标记的,系统会负责他们的引用计数,当引用计数为 0 时,它们会被销毁        String^ HelloCx(String^ name);         String^ HelloCpp(String^ name);        // 由 C# 调用,用于设置 ICallback 对象        void SetCallback(ICallback^ callback);        // 由 C++/CX 调用,用于通过 ICallback 向 C# 发送数据        property static ICallback^ GlobalCallback;    };}

DemoCx.cpp

/* * 演示 C#, C++/CX, C/C++ 间的通信 * * 本例是 C++/CX 部分 * * 为了支持 Windows Runtime Component 这种方式,所以引入 Microsoft created the Visual C++ component extensions (C++/CX),可以将其看作是连接“调用者”和“C/C++”之间的桥梁,元数据是 windows metadata (.winmd) files * 为了让“调用者”调用 Windows Runtime Component,所以 C++/CX 会有自己的一些数据类型,比如字符串是 Platform::String^ 类型的,这样才能让“调用者”调用 * 关于 C++/CX 的相关知识请参见:https://msdn.microsoft.com/en-us/library/hh755822.aspx */#include "pch.h" #include "DemoCx.h" #include "CppCx.h" #include "cppHelper.h"using namespace NativeDll;String^ DemoCx::HelloCx(String^ name){    // 如果 C# 端设置了 ICallback 对象,则可以在 C++/Cx 端向 C# 端发送数据    if (GlobalCallback != nullptr)        GlobalCallback->Cx2Cs("c++/cx to cs");    return "hello: " + name;}// 由 C# 调用,用于设置 ICallback 对象void DemoCx::SetCallback(ICallback^ callback){    GlobalCallback = callback;}String^ DemoCx::HelloCpp(String^ name){    // C++/CX 与 C/C++ 通信时,如果要传递字符串,则要对字符串做转换    string cppName = ws2s_3(std::wstring(name->Data()));    // C++/CX 调用 C/C++    CppCx cppCx;    string cppResult = cppCx.Hello(cppName);    String^ cxResult = ref new Platform::String(s2ws_3(cppResult).c_str());    return cxResult;}


3、托管代码层
Cx.xaml

<Page    x:Class="NativeDemo.Demo.Cx"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:NativeDemo.Demo"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d">    <Grid Background="Transparent">        <StackPanel Margin="120 0 0 0">            <TextBlock Name="lblMsg" TextAlignment="Left" FontSize="24.667" TextWrapping="Wrap" />        </StackPanel>    </Grid></Page>

Cx.xaml.cs

/* * 演示 C#, C++/CX, C/C++ 间的通信 *  * 本例是 C# 部分 *  *  * C# 与 C++/CX 间通信;C++/CX 与 C/C++ 间通信;C# 通过 C++/CX 与 C/C++ 间通信 */using System;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Navigation;namespace NativeDemo.Demo{    public sealed partial class Cx : Page    {        public Cx()        {            this.InitializeComponent();        }        protected override void OnNavigatedTo(NavigationEventArgs e)        {            NativeDll.DemoCx demoCx = new NativeDll.DemoCx();            MyCallback myCallback = new MyCallback();            myCallback.MessageReceived += myCallback_MessageReceived;            demoCx.SetCallback(myCallback);            // C# 调用 C++/CX            lblMsg.Text += demoCx.HelloCx("cs to c++/cx");            lblMsg.Text += Environment.NewLine;            // C# 通过 C++/CX 调用 C/C++            lblMsg.Text += demoCx.HelloCpp("cs to c++/cx to c/c++");            lblMsg.Text += Environment.NewLine;        }        async void myCallback_MessageReceived(object sender, MessageEventArgs e)        {            MyCallback myCallback = (MyCallback)sender;            await lblMsg.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>            {                lblMsg.Text += e.Message;                lblMsg.Text += Environment.NewLine;            });        }    }    // 实现 C++/CX 中的 ICallback 接口    public class MyCallback : NativeDll.ICallback    {        // 收到 C++/CX 直接发送过来的数据,或者 C/C++ 通过 C++/CX 发送过来的数据        public void Cx2Cs(string message)        {            OnMessageReceived(new MessageEventArgs { Message = message });        }        public event EventHandler<MessageEventArgs> MessageReceived;        protected virtual void OnMessageReceived(MessageEventArgs e)        {            EventHandler<MessageEventArgs> handler = MessageReceived;            if (handler != null)                handler(this, e);        }    }    public class MessageEventArgs : EventArgs    {        public string Message { get; set; }    }}



二、演示 android app native开发
1、native 层(C 语言)
cHello.h

#ifndef _MYHEAD_CHELLO_#define _MYHEAD_CHELLO_#ifdef __cplusplusextern "C"{#endifchar *hello(const char *name);#ifdef __cplusplus}#endif#endif

cHello.c

#include "cHello.h"#include <stdlib.h>char *str_concat2(const char *, const char *);char *hello(const char *name){    return str_concat2("hello: ", name);}char *str_concat2(const char *str1, const char *str2){    char *result;    result = (char *)malloc(strlen(str1) + strlen(str2) + 1);    if (!result)    {        exit(EXIT_FAILURE);    }    strncpy(result, str1, strlen(str1) + 1);    strncat(result, str2, strlen(str1) + strlen(str2) + 1);    return result;}


2、native 层(C++)
CppHello.h

#ifndef _MYHEAD_CPPHELLO_#define _MYHEAD_CPPHELLO_#include <string>using namespace std;namespace MyNs{    class CppHello    {    public:        string Hello(string name);    };}#endif

CppHello.cpp

#include "CppHello.h"using namespace MyNs;string CppHello::Hello(string name){    return "hello: " + name;}


3、jni层
jniDemo.h

#include <jni.h>#ifndef _Included_com_cnblogs_webabcd_jniDemo#define _Included_com_cnblogs_webabcd_jniDemo#ifdef __cplusplusextern "C" {#endif// 注意函数名的命名规则JNIEXPORT jstring JNICALL Java_com_example_androidnative_MainActivity_helloJniCpp(JNIEnv *env, jobject obj, jstring name);JNIEXPORT jstring JNICALL Java_com_example_androidnative_MainActivity_helloJniC(JNIEnv *env, jobject obj, jstring name);#ifdef __cplusplus}#endif#endif

jniDemo.cpp

/* * jni(Java Native Interface) - 详细文档参见 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/ * ndk(Native Development Kit) - 下载 ndk 后,其目录内有详细的文档 * cygwin - 在 windows 平台上运行的类 UNIX 模拟环境,可以调用 ndk 编译 so * * * 为了使 jni 能支持 c++ 需要这么做: * 1、将本文件的后缀名从 .c 修改为 .cpp(c++ 文件的扩展名可以通过 Android.mk 的 LOCAL_CPP_EXTENSION 指定) * 2、按本例的方式配置 Application.mk 文件(如果只想支持 c 语言的话,则可以不要此文件) */#include "jniDemo.h"#include "CppHello.h"#include "cHello.h"void jni2java(JNIEnv *);// 对应 MainActivity 类中的 public native String helloJniCpp(String name); 注意函数的命名规则JNIEXPORT jstring JNICALL Java_com_example_androidnative_MainActivity_helloJniCpp(JNIEnv *env, jobject obj, jstring name){    jni2java(env);    MyNs::CppHello cppHello;    const char *charName = env->GetStringUTFChars(name, 0); // jstring to char    std::string stringName(charName); // jstring to string    std::string stringResult = cppHello.Hello(stringName);    const char *charResult = stringResult.data(); // string to char    jstring jstringResult = env->NewStringUTF(charResult); // char to jstring    return jstringResult;    /*     * 调用 jni 函数时注意(对于 C 和 CPP 来说,JNIEnv 的含义不同,具体请查看文档):     * 1、C 的用法示例:jstring jstringResult = (*env)->NewStringUTF(env, charResult); // char to jstring     * 2、CPP 的用法示例:jstring jstringResult = env->NewStringUTF(charResult); // char to jstring     */}// 对应 MainActivity 类中的 public native String helloJniC(String name); 注意函数的命名规则JNIEXPORT jstring JNICALL Java_com_example_androidnative_MainActivity_helloJniC(JNIEnv *env, jobject obj, jstring name){    jni2java(env);    const char *charName = env->GetStringUTFChars(name, 0); // jstring to char    char *charResult = hello(charName);    jstring jstringResult = env->NewStringUTF(charResult); // char to jstring    free(charResult);    return jstringResult;}// 调用 MainActivity 类中的 public static void helloJava(String message); 函数void jni2java(JNIEnv *env){    const char *className = "com/example/androidnative/MainActivity"; // 注意类名规则    jclass cla = env->FindClass(className);    // 第三个参数中:(Ljava/lang/String;)代表 java 中的被调用的函数的参数是 String 类型;V 代表 java 中的被调用的函数的返回值是 void 类型    jmethodID method = env->GetStaticMethodID(cla, "helloJava", "(Ljava/lang/String;)V");    jstring result = env->NewStringUTF("jni to java");    env->CallStaticVoidMethod(cla, method, result);}

编译相关
Application.mk

APP_STL := stlport_static #以静态链接的方式使用stlport版本的STLAPP_CPPFLAGS := -fexceptions -frtti #允许异常功能,及运行时类型识别  APP_CPPFLAGS +=-std=c++11 #允许使用c++11的函数等功能  APP_CPPFLAGS +=-fpermissive  #此项有效时表示宽松的编译形式,比如没有用到的代码中有错误也可以通过编  

Android.mk

LOCAL_PATH := $(call my-dir)#模块1include $(CLEAR_VARS) #清除 LOCAL_MODULE, LOCAL_SRC_FILES 之类的变量LOCAL_CPP_EXTENSION := .cpp # C++ 文件的扩展名LOCAL_MODULE := jniDemo # 模块名。如果模块名为“abc”,则此模块将会生成“libabc.so”文件。LOCAL_SRC_FILES := jniDemo.cpp CppHello.cpp cHello.c # 需要编译的源文件include $(BUILD_SHARED_LIBRARY) # 编译当前模块#模块2


4、托管代码层
MainActivity.java

/* * 演示 java 如何通过 jni 与 C/C++ 互相通信 */package com.example.androidnative;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends Activity {    private static TextView txtMsg;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                txtMsg = (TextView) this.findViewById(R.id.txtMsg);                // 加载 so        System.loadLibrary("jniDemo");                // java 调用 jni, c        String resultC = helloJniC("java to jni to c");        txtMsg.append(resultC);        txtMsg.append("\n");                // java 调用 jni, c++        String resultCpp = helloJniCpp("java to jni to c++");        txtMsg.append(resultCpp);        txtMsg.append("\n");    }    // native function(对应的 jni 函数参见 jniDemo.cpp)    public native String helloJniC(String name);    public native String helloJniCpp(String name);        // jni 调用 java    public static void helloJava(String message)    {        txtMsg.append(message);        txtMsg.append("\n");    }}



三、演示 ios app native开发(无论是 oc 还是 swift 都是 native 开发,本例演示 oc, c, c++ 混编)
ViewController.h

////  ViewController.h//  IosNative////  Created by wanglei on 4/24/15.//  Copyright (c) 2015 webabcd. All rights reserved.//#import <UIKit/UIKit.h>@interface ViewController : UIViewController@end

ViewController.mm

/* * 演示 objective-c 如何与 C/C++ 互相通信 *  * objective-c 是面向对象的 c 语言,本身就是 Native 的,完全兼容 c 语言,可以与 C/C++ 混编 * * 注:为了支持 C++ 需要把本文件的后缀名由 .m 修改为 .mm */#import "ViewController.h"#include <string>@interface ViewController ()@end@implementation ViewControllerchar *hello(const char *);class CppHello;- (void)viewDidLoad{    [super viewDidLoad];    [self helloC:@"oc to c"];    [self helloCpp:@"oc to c++"];}// oc 调用 c- (void)helloC:(NSString *)name{    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 200, 20)];    [self.view addSubview:label];        const char *charName = [name UTF8String]; // nsstring to char    char *charResult = hello(charName);    NSString *nsstringResult = [[NSString alloc] initWithCString:charResult encoding:NSUTF8StringEncoding]; // char to nsstring    free(charResult);        label.text = nsstringResult;}// oc 调用 c++- (void)helloCpp:(NSString *)name{    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 200, 20)];    [self.view addSubview:label];        string stringName = [name UTF8String]; // nsstring to string    MyNs::CppHello cppHello;    string stringResult = cppHello.Hello(stringName);    NSString *nsstringResult = [[NSString alloc] initWithCString:stringResult.c_str() encoding:NSUTF8StringEncoding]; // string to nsstring        label.text = nsstringResult;}char *hello(const char *name){    // c 调用 oc(别忘了 #import <Foundation/Foundation.h>,本例中不用是因为 UIViewController 已经导入这个头文件了)    NSLog(@"c to oc");        char *s = "hello: ";        char *result;    result = (char *)malloc(strlen(s) + strlen(name) + 1);    if (!result)        exit(EXIT_FAILURE);        strncpy(result, s, strlen(s) + 1);    strncat(result, name, strlen(s) + strlen(name) + 1);        return result;}using namespace std;namespace MyNs{    class CppHello    {    public:        string Hello(string name);    };}string MyNs::CppHello::Hello(string name){    // c++ 调用 oc(别忘了 #import <Foundation/Foundation.h>,本例中不用是因为 UIViewController 已经导入这个头文件了)    NSLog(@"c++ to oc");        return "hello: " + name;}@end



OK
[源码下载]

更多相关文章

  1. Ted Mosby - 一个MVP框架的软件架构
  2. Android(安卓)Camera源码函数结构
  3. android开发每日汇总【2011-11-26】
  4. 不可或缺 Windows Native (25) - C++: windows app native, andr
  5. [转]Android(安卓)技术专题系列之九 -- 图形系统
  6. Android(安卓)系统启动过程
  7. cocos2d-x编译到android平台后,增加返回键和菜单键的支持
  8. Android中WebView页面交互
  9. android 2.3 r1 中文 api (58) —— TabHost

随机推荐

  1. Android 子线程更新UI
  2. Android下实现短信的收发
  3. android从相册中获取图片并将其显示在当
  4. ANDROID STUDIO “CANNOT RESOLVE SYMBOL
  5. 将 Android(安卓)项目迁移至 Kotlin Coro
  6. android 获取锁屏,解锁的方法
  7. Android(安卓)app调用第三方地图(百度地图
  8. 【Android】设置代理
  9. Android 使用 DowanloadManager 实现下载
  10. Android 四大组件+五大布局