C++调用objectC 和 C++调用java

讲讲c++如何统一不同平台的接口吧

c++如何调用objectC

ios中 c++ 的文件可以用 .cpp 和 .mm 来结尾
区别是:
.mm :带有这种扩展名的源代码文件,除了可以包含objective-c和C代码以外还可以包含C++代码。
.cpp:只能编译C++

所以,如果要从c++ 中调用 ios 底层的内容, .mm 文件必不可少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
.h 文件
#ifndef Test_hpp
#define Test_hpp

#include"cocos2d.h"
#include <stdio.h>
class TestFun {
public:
TestFun();
~TestFun();
std::string getStrFromOC();
};
#endif /* Test_hpp */
.mm 文件

#include "Test.hpp"
#import "AppController.h"

TestFun::TestFun(){
cocos2d::log("TestFun create");
}
TestFun::~TestFun(){

}
// .mm 文件是可以直接调用 oc 中的方法的
std::string TestFun::getStrFromOC(){
return [[AppController myTestFun] UTF8String];
}

//AppController.mm 文件添加内容

+ (NSString *)myTestFun
{
return @"TestStr from AppController.h";
}

//调用部分在 AppDelegate

LuaStack* stack = engine->getLuaStack();
stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));

auto testClass = new TestFun();
std::string str = testClass->getStrFromOC();
cocos2d::log("fun call after is %s",str.c_str());

//打印 log

TestFun create
fun call after is TestStr from AppController.h
[LUA-print]
**********

由此可见 c++ 调用object-C 比较容易,更改后缀为.mm 就可以使用

c++如何调用java

既然是懒人,那就直接使用Test class 来做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
.h 文件
#ifndef Test_hpp
#define Test_hpp

#include"cocos2d.h"

class TestFun {

public:
TestFun();
~TestFun();
std::string getStrFromOC();
//添加获取bunleId 的函数
std::string getBundleID();
};
#endif /* Test_hpp */

.mm 文件
<!-- 添加新的函数 getBundleID-->
std::string TestFun::getBundleID(){
std::string bundleId = "";
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
<!-- 获取ios的上面已经写过了这里就不啰嗦了 -->
bundleId = "";
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
<!-- 添加宏 判断平台 -->
#include "platform/android/jni/JniHelper.h"
<!-- 引入头java native interface 需要使用的文件 -->
cocos2d::JniMethodInfo t; //jni 方法结构体 下面的使用需要这个结构体
if(cocos2d::JniHelper::getStaticMethodInfo(t, "org/cocos2dx/lua/AppActivity", "getBundleID", "()Ljava/lang/String;")){
<!-- getBundleID 传递参数为空 返回string 类型 -->
jstring bundle = (jstring) t.env->CallStaticObjectMethod(t.classID, t.methodID);
<!-- 需要把返回的jstring 转化为 string -->
bundleId = cocos2d::JniHelper::jstring2string(bundle);
}
#endif
return bundleId;
}


<!-- 查看了下jni 的写法 -->
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
这个是jni 方法的结构体

getStaticMethodInfo 方法内容
1.判断是否传递参数
2.获取jni 环境
3.获取所要调用的class 的id
4.获取所需要调用静态函数的id
5.把所有的信息插入到结构体中
6.返回 true

java文件
public static String getBundleID() {
String packageName = "";
try {
// ---get the package info---
packageName = myContext.getPackageName();
if (packageName == null || packageName.length() <= 0) {
return "";
}
} catch (Exception e) {
Log.e("VersionInfo", "Exception", e);
}
return packageName;
}

c++调用部分
AppDelegate 文件 (不要忘记引用头文件)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
auto myClass = new TestFun();
std::string myStr = myClass->getBundleID();
cocos2d::log("bundle id is %s",myStr.c_str());
#endif

Android.mk 文件 需要在 LOCAL_SRC_FILES 中添加
../../Classes/Test.mm \

执行编译

然而编译不过。。。

jni/../../Classes/AppDelegate.cpp:79: error: undefined reference to 'TestFun::TestFun()'
jni/../../Classes/AppDelegate.cpp:80: error: undefined reference to 'TestFun::getBundleID()'
jni/../../Classes/AppDelegate.cpp:83: error: undefined reference to 'TestFun::getStringWithParams()'
collect2: error: ld returned 1 exit status

更改Test.mm 为 Test.cpp 更改Android.mk 文件中写入的为
../../Classes/Test.cpp \

再次编译,,过了 完美

D/cocos2d-x debug info( 1794): TestFun create
D/cocos2d-x debug info( 1794): bundle id is org.cocos2dx.Hello

adb logcat 中日志文件

上面我们写了一个获取java 字符串的函数,如果我们想向java 中传递函数呢 ?
接着来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
.h 文件
#ifndef Test_hpp
#define Test_hpp

#include"cocos2d.h"

class TestFun {

public:
TestFun();
~TestFun();
std::string getStrFromOC();
std::string getBundleID();
<!-- 添加传递参数的函数 -->
std::string getStringWithParams();
};
#endif /* Test_hpp */

.cpp 文件
<!-- 实现部分比上面多了 getStringWithParams -->
std::string TestFun::getStringWithParams(){
std::string returnStr = "";
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"
cocos2d::JniMethodInfo t;
if(cocos2d::JniHelper::getStaticMethodInfo(t, "org/cocos2dx/lua/AppActivity", "getMyString", "(Ljava/lang/String;)Ljava/lang/String;")){
cocos2d::log("getStringWithParams from c++");
<!-- 需要传递给java的字符串 -->
std::string toJavaStr = "from c++ params";
<!-- 需要转化为 jstring jni需要类型 -->
jstring stringArg1 = t.env->NewStringUTF(toJavaStr.c_str());
<!-- CallStaticObjectMethod 函数 第三个是需要传递的数据 -->
jstring myString = (jstring) t.env->CallStaticObjectMethod(t.classID, t.methodID,stringArg1);
returnStr = cocos2d::JniHelper::jstring2string(myString);
}
#endif
return returnStr;
}

AppDelegate 文件中修改
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
auto myClass = new TestFun();
std::string myStr = myClass->getBundleID();
cocos2d::log("bundle id is %s",myStr.c_str());
<!-- 新添加 getStringWithParams -->
std::string returnStr = myClass->getStringWithParams();
cocos2d::log("return str is %s",returnStr.c_str());
#endif

java 文件添加函数

public static String getMyString(String s) {
Log.d("c++ call getMyString params is ",s);
return "return form java ";
}


Android.mk 文件
依然依旧
../../Classes/Test.cpp \

编译通过

adb logcat
c++ call getMyString params is ----> java 文件内容
std::string toJavaStr = "from c++ params"; ----> c++文件传递给java
D/c++ call getMyString params is ( 1794): from c++ params
D/cocos2d-x debug info( 1794): return str is return form java

如上,通过.mm 文件可以直接调用oc 中函数,在cpp 文件中通过jni 可以调用java 也可以相互传递值

假如还想知道怎样从java 中调用c++ 该如何 ???好累,下次再写。。。