[源码下载]

不可或缺 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 __cplusplus
extern "C"
{
#endif char *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) + );
if (!result)
{
exit(EXIT_FAILURE);
} strncpy(result, str1, strlen(str1) + );
strncat(result, str2, strlen(str1) + strlen(str2) + );
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 __cplusplus
extern "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, ); // 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, ); // 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版本的STL
APP_CPPFLAGS := -fexceptions -frtti #允许异常功能,及运行时类型识别
APP_CPPFLAGS +=-std=c++ #允许使用c++11的函数等功能
APP_CPPFLAGS +=-fpermissive #此项有效时表示宽松的编译形式,比如没有用到的代码中有错误也可以通过编

Android.mk

LOCAL_PATH := $(call my-dir)

#模块1
include $(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 ViewController char *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(, , , )];
[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(, , , )];
[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) + );
if (!result)
exit(EXIT_FAILURE); strncpy(result, s, strlen(s) + );
strncat(result, name, strlen(s) + strlen(name) + ); 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
[源码下载]

不可或缺 Windows Native (25) - C++: windows app native, android app native, ios app native的更多相关文章

  1. App Transfer:苹果允许iOS App从一个开发者帐号转至另一个开发者账号

    App Transfer:苹果允许iOS App从一个开发者帐号转至另一个开发者账号 苹果在WWDC上宣布超过30万的开发者为iOS平台开发超过90万的应用,你可能会想到有人想出售或者购买app. 现 ...

  2. 极速创建 IOS APP !涛舅舅苹果 IOS APP自助生成系统正式上线

    经过大量的测试和开发工作,涛舅舅苹果 IOS APP自助生成系统正式上线! 本系统主要功能: 1.用最最简单的方式将H5网站打包生成一个苹果APP 2.只需要提供APP标题,H5网站首页url地址,一 ...

  3. 极速创建 IOS APP !涛舅舅苹果 IOS APP自助生成系统!不用证书、不用越狱、永久可用

    不用签名将网页封装成苹果APP,无需苹果企业签名,IPA签名,ios签名,免越狱安装 (本方法只支持网站封装app,原生的用不了,详细请咨询客服) 近期很多朋友问我把网站变成app的方法,原因很多种, ...

  4. 为什么我的 app:actionViewClass="android.widget.SearchView"和app:showAsAction="ifRoom|collapseActionView"才有

    http://blog.csdn.net/cdnight/article/details/48029911 <item android:id="@+id/action_search&q ...

  5. Android Studio 提示Error running app: No Android facet found for app

    错误解决办法如下: 可以通过以下几个步骤解决该问题: 1) 点击菜单File -> 选择Project Structure, 或使用快捷键 (Ctrl+Alt+Shift+S) 打开”Proje ...

  6. 用Xamarin和Visual Studio编写iOS App

    一说开发 iOS app,你立马就会想到苹果的开发语言 Objective C/Swift 和 Xcode.但是,这并不是唯一的选择,我们完全可以使用别的语言和框架. 一种主流的替换方案是 Xamar ...

  7. 勾勾街——一个专注于免越狱免签名的苹果ios APP打包生成的网站

    自涛舅舅研发的“苹果ios APP自助生成系统”上线以来,每天都有大量的用户注册和生成免越狱app,为什么? 因为我们有明显的技术优势,APP不需要上架appstore, 生成APP又不需要企业签名证 ...

  8. 勾勾街:一个专业的苹果ios app 自助打包的网站,免越狱,免证书签名

    众所周知,苹果的APP开发是需要基于MAC环境的,而我们很多的开发者并没有这样的条件,如果单单为发布一款app就去买一台价格昂贵的MAC那成本就太高了! 就算你有一台MAC,也有能力自己开发出一款基于 ...

  9. Deploying JRE (Native Plug-in) for Windows Clients in Oracle E-Business Suite Release 12 (文档 ID 393931.1)

    In This Document Section 1: Overview Section 2: Pre-Upgrade Steps Section 3: Upgrade and Configurati ...

随机推荐

  1. Canny算子边缘检测(cvCanny)

    Canny是常用的边缘检测方法,其特点是试图将独立边的候选像素拼装成轮廓. John Canny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法. ...

  2. java指定路径写、读文件

    package com.util; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; ...

  3. linux奇技淫巧 2

    压缩解压==================================================================================== unzip xx.zi ...

  4. Atitit 图像处理知识点  知识体系 知识图谱v2

    Atitit 图像处理知识点  知识体系 知识图谱v2 霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法.主要用来从图像 ...

  5. Atitti 图像处理 图像混合 图像叠加 blend 原理与实现

    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现 混合模式 编辑 本词条缺少信息栏,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 混合模式是图像处理技术中的一个技术名词,不 ...

  6. 每天一个linux命令(8):cp 命令

    cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...

  7. Struts2学习笔记 - Action篇<配置文件中使用通配符>

    有三种方法可以使一个Action处理多个请求 动态方法调用DMI 定义逻辑Acton 在配置文件中使用通配符 这里就说一下在配置文件中使用通配符,这里的关键就是struts.xml配置文件,在最简单的 ...

  8. .NET面试题解析(06)-GC与内存管理

      系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 GC作为.NET的重要核心基础,是必须要了解的.本文主要侧重于GC内存管理中的一些关键点,如要要全面深入了 ...

  9. 最简单的可取消多选效果(以从水果篮中挑选水果为例)【jsDEMO】

    [功能说明] 最简单的可取消多选效果(以从水果篮中挑选水果为例) [html代码说明] <div class="box" id="box"> < ...

  10. vc++用ADO方式连接oracle问题

    今天装了个oracle客户端,准备写个访问远程oracle的程序.用的是vs2010,采用ADO的连接方法连接oracle,结果运行的时候总是报下面的错: 从提示可以看出是没有找到OraOLEDBup ...