2018-06-03 22:56:48 jianin45 阅读数 367

本文所用各版本信息:
Xcode9.2 + swift4版本
cocos2d-x v3.17 中文官方网站

集成思路

首先网上给出一个C系的思路,本人未亲测,并且以C调用lua,绕过了cocos2d-x的调用思路,不觉得这种方式很好,所以弃之;

C语言调用思路

本文思路如图:
swift->objective-c->c++->lua
首先swift与objective-c的互相调用非常方便,其次oc只需要将.m文件写成.mm就可以在实现中直接调用c++方法,并且c++可以直接绑定lua,这样一来,就实现了,ios系语言写主框架,lua写游戏逻辑,直接通过ViewController展现就可以了;并且lua脚本可以像资源添加的方式直接在文件夹中替换,非常方便;基于以上思路,说干就干;

首先你需要一个swift项目

新建一个swift语言写的工程,我们默认你已经会用Xcode做这件事了,于是,工程的结构先大致看一下;

Nothing项目结构

image_1cf2g61423hj8ks12ngn544ov1g.png-122.4kB

这里是我自己的swift工程,上面的是总结构,下面的是内部工程结构,我们这里只关注一下bridge,首先创建一个CocosViewController的控制器,这里的控制器可以是OC类型的,也可以使用swift类型的(由于我们需要用OC做桥接文件,所以需要我们创建一个OC的类,我这里自己写了一个单例用来做桥接,所以控制器就无所谓是OC还是swift了),用来呈现我们用cocos2dx-lua展现的游戏页面;在swift工程中添加OC文件会自动生成桥接文件,名字如图;另外还需要注意一点,CocosViewController的.m文件要修改成.mm类型,这样就可以在实现中直接调用C++的类了;

创建好后先不要动,我们再来创建一个OC类型的单例,用来进行引擎的初始化操作,以及对lua游戏操作进行封装,我自己命名为LuaBridge
image_1cf2h2kvq7381eho18ieh5v1s5o1t.png-12kB

#import "LuaBridge.h"
#include "CocosLua.hpp"

@interface LuaBridge()
{
    CocosLua _cocosLua;
}

@end

@implementation LuaBridge

- (instancetype)init
{
    self = [super init];
    if (self) {
        _cocosLua = CocosLua();

    }
    return self;
}

static LuaBridge* _bridge = nil;

+ (instancetype)shared {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _bridge = [[LuaBridge alloc] init];
    });
    return _bridge;
}
@end

上面出现的CocosLua是一个c++的类,在工程中自己创建的;创建它的目的是用来封装cocos2dx-lua的操作,这个类直接被隐藏在LuaBridge单例中,在实际应用过程中可能用的不是很多,我们这里出现它只是为了说明本文的类型结构;

#ifndef CocosLua_hpp
#define CocosLua_hpp

#include <iostream>

class CocosLua {

public:
    CocosLua();
    ~CocosLua();

public:
    void cocos_lua();
};

#endif /* CocosLua_hpp */

创建一个cocos2dx-lua项目

首先我们需要去cocos官网上下载cocos2dx源码,链接在本文开始,我自己下载的是v3.17版本,下载的是zip包,解压后如下图:

image_1cf2mkgfu1m1uk0i13ppv7jieh3h.png-77.4kB

接下来打开终端,我们创建一个lua项目;

image_1cf2mm4hr2387mi1snp1iv51gtb3u.png-82.5kB

一路cd到我们下载的cocos2dx文件夹下,然后:

$ cd tools/cocos2d-console/bin/

到上面的这个目录下新建工程,使用下面的命令格式:

cocos new <game name> -p <package identifier> -l <language> -d <location>
<game name> 工程名
<package identifier> 包名,bundle id
<language> 所用语言 cpp lua js
<location> 项目创建路径
$ ./cocos new Nothing-lua -p com.charles.nothing -l lua -d /Users/dizi/Desktop

image_1cf2n16id1lfp13phripbgh13ta4b.png-153.7kB

image_1cf2n2esh15vo18se12q01i7dih54o.png-29kB

整合swift项目与lua项目

如果你做到这一步,那么我们离成功不远了;接下来我们要把lua项目里的资源拷贝到swift项目中,具体跟着我一步一步做;

  1. 把lua项目下frameworks/cocos2d-x文件夹拖动到swift目录下:
    image_1cf2ni2nnkpq1pmrsbd1iippri55.png-160.2kB
    这里说一点,如果工程是用git管理,因为cocos2d-x下文件比较多,而且是cocos2dx代码文件,所以不必要上传,可添加.gitignore文件:
    image_1cf2o45re1ahs1lvjn8mca14be5i.png-16.3kB

  2. 把lua项目下frameworks/runtime-src/Classes文件夹拖动到swift目录下:
    image_1cf2o6cm9rhe1tj416tl1acf8285v.png-197.8kB

  3. 在swift项目目录下新建Resources文件夹,将lua项目中的如图三项拷贝进该文件夹下,这样以后lua的所有资源则将全部在该目录下替换,不需要修改工程中其他地方:
    image_1cf2obieh1vrtujma7ucml86d6c.png-112.3kB

  4. 将刚刚添加的文件引用到工程项目中:
    image_1cf2ogs2gai2rj01e701jks1q2h79.png-75.4kB
    image_1cf2pbtk51lrv1kek18me1i5brlh8j.png-68.5kB
    注意我们的coco2d-x目录并不需要一并引入到工程中,我们不会用到它(不引用它并不说不会用到,不要删掉,不要删掉,不要删掉!!!);
    PS:这里注意蓝色文件夹和黄色文件夹的区别;

工程环境配置

接下来到了重头戏,工程环境配置,这个部分我们需要耐心一点,因为有很多路径需要我们自己去找,还要搞清楚几个不同的工程项目配置,我们一步一步来;

  1. 引入工程文件,这几个工程文件分别生成cocos-lib以及调拭用.a库,以下依次:
    image_1cf2vge2nmebc02hcgk8k1a199g.png-241.5kB
    image_1cf2vjknh14co12bq15jqahuh0a9t.png-103.2kB
    image_1cf2vl0kf1skll42p86qi11k16aa.png-156.1kB

  2. 接下来配置资源库,点击工程TARGETS->Build Phases,在Target Dependencies中添加:
    image_1cf2vs1jffgj8avof61vg11iuaan.png-85.6kB
    在Link Binary With Libraries中添加如下支持库,其中lib文件需要打开Add other添加,按shift + command + G,在其中输入/usr/lib
    image_1cf304l9cja61nu71r9h1l8b539b4.png-118.7kB
    image_1cf309lts1b921oan4rhvkd1svebh.png-110.7kB

  3. cocos2dx不支持bitcode,在buildsetting中Enable Bitcode改为NO;
    image_1cf30d889rs6173d8s411e0i5jbu.png-21.7kB
    C++编译器部分:
    image_1cf30ekpb1omd1rj61m56qo1eracb.png-26.4kB

  4. Header Search Paths中添加:

$(inherited)
$(PROJECT_DIR)/cocos2d-x/cocos
$(PROJECT_DIR)/cocos2d-x/external/lua/tolua
$(PROJECT_DIR)/cocos2d-x/external/lua/lua
$(PROJECT_DIR)/cocos2d-x/external/lua
$(PROJECT_DIR)/cocos2d-x/external
$(PROJECT_DIR)/cocos2d-x/Classes

image_1cf30m5opf41hq513ib1eekflbco.png-130.9kB
5. 引入工程配置:
cocos2d_libs.xcodeproj工程配置中,确保以下架构都支持;
image_1cf30qh2sddp1mi95kj89o1725d5.png-52.8kB
cocos2d_lua_bindings.xcodeproj工程配置中,确保以下支持平台为iOS;
image_1cf30sk2o1211j4t88f11lt172dff.png-98.9kB
6. 好了,开始编译你的工程吧!

去倒杯水吧,这个过程会很久。。。

image_1cf31g68atfq3l31v3uf4n1nm6fs.png-8.4kB
Congratulations! 至此,工程已经全部配置完毕,你已经解决一个大Boss了;
今天就到这里吧,之后我们再续如何用swift调用lua 手把手教你swift项目添加cocos2dx-lua(2)

2015-07-28 16:22:16 vkooy 阅读数 2184

集成了银联支付后,又集成支付宝支付,但是遇到了一个问题,解决了很久才解决:

//获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode

   id<DataSigner> signer =CreateRSADataSigner(privateKey);

这句代码一直报错,解决方案:

集成银联的时候将类后缀改为.mm文件,于是将DataSigner.m文件的后缀名也改为.mm文件,此时编译、运行都正常。


希望后人珍惜时间,少走弯路,健康生活。

2015-08-20 20:43:48 chingxuyuan 阅读数 426

 1,新建一swift项目

2, 把BaiduMapAPI.framework放到工程目录下,然后导入项目中去

3,导入那几个系统库

4,在TARGETS->Build Settings->Other Linker Flags 中添加-ObjC。用搜索,快一点儿


5,引入mapapi.bundle资源文件

6,建一个.mm后缀的源文件,以及自动生产桥接文件

7,编译一下出来个错


 解决方法:指定一下库的路径,配置fraework Search Path



8,再编译,再出个错



原因:未来Watch应用须包含Bitcode,iOS不强制,但Xcode7默认会开启Bitcode

解决方法:关闭








2019-03-21 15:41:46 liuyong0214 阅读数 374

场景描述:

OC项目集成Swift三方库,在引用Swift三方库的时候出现的报错。

奇怪之处在于,.m文件是可以引用的,在.h文件是不能引用,直接报上面的错(一度使我极度郁闷,更郁闷的是第二天居然不报错了),还是把自己的解决办法说一下。

下面的两个设置也试过,在我项目中不管用(可能项目中存在.mm文件,如果存在,可能的原因是您使用objective - c + +。modules不适用c++),点击项目->targets->build settings 搜索module将
1.enable modules
2.link frameworks automatically
两个设置成YES

解决办法:

由于我要把三方写在一个公共方法里面,所以我创建了OC单例,才会在一直出现上面的报错。

于是我想到了Swift单例,通过创建Swift单例,在去OC项目中引用Swift单例,从中这样解决,以下是代码:

import UIKit

import MatomoTracker

@objc

open class MatomoTrackerObj: NSObject {

    

    static let _sharedMatomoTrackerObj = MatomoTrackerObj()

    @objc open class func sharedMatomoTrackerObj() -> MatomoTrackerObj {

        return _sharedMatomoTrackerObj

    }

    

    @objc open func getMatomoTracker() -> MatomoTracker {

        let matomoTracker = MatomoTracker(siteId: "", baseURL: URL(string: "")!)

        return matomoTracker

    }

}

2014-08-02 14:34:47 sunyonggao 阅读数 434

/*

1.扩展名

.c       C文件

.cc,.cpp C++文件

.h  头文件

.m  objectivec原文件

.mm objectivec++原文件


2.swift不同,OC不支持嵌套的/*注释


3.常用类

 NSString

 NSNumber 可以表示整数,floatdouble

 上面两个基本类型一旦定义之后,其值不可以改变。

 

 NSString提供一个mutable版本,NSMutableString

 

 4.再定义每个类时,如果没有其他的继承,则必须继承NSObject类。

 

 5.idOC中定义的一个特殊类型,可以代表任意类型类似 NSObject * void *

 nil = NULL

 

 6.bool变量 YES NO

 

 7.swift一样只支持但继承,协议支持多继承。

 

 8.OC中所有的成员函数都是虚函数

 

 9.异常处理块@try @catch @finally

 

 10.用#import包含头文件,包含C语言中的防止重复包含语句。

 ifndef 。。#define endif

 

 11.@public @protected @privateC++类似,默认的数据是@protected

 @private的变量不能被子类继承

 

 12.OC中的重载识别的是函数名+标签,不区分函数类型和参数类型

 

 13.只在类文件中定义的类方法,作为默认私有的函数。不能通过实例来使用。

*/


Person.h

@interface Person: NSObject

//带property修饰符的成员变量默认是public的,其他对象可以修改之。
@property NSString *personFirstName;
@property NSString *personLastName;
@property int      yearOfBirth;

//只读属性的定义方法
@property (readonly) NSString *readonlyName;

//给所有人统一进行编号
+(int) getPersonNumber;

//所有以init开头的函数作为构造函数使用
-(id) init:(NSString *)firstname secondname:(NSString *)secondname;

//对象作为返回值时,也必须用指针
-(NSString *) getFirstName;
-(NSString *) getLastName;

//-表示实例方法,+表示类方法
//(void)返回值,参数(Type)paraname 其中参数名字定义和声明可以不同。
// 和swift类方法一样,第二个参数开始必须加ExtenalParameter
// 如果参数是一个对象的话,必须传指针
-(void) setName:(NSString *)first sencondParaExtenalPara:(NSString *)second;
//重载中,OC中的函数识别的是函数名+标签,下面的函数和上面的一样setName:secondParaExtenalPara
//所以编译会报错,重名函数
//-(void) setName:(NSString *)first sencondParaExtenalPara:(int)second;
-(void) setName:(NSString *)first second:(NSString *)second; //这个函数可以重载
@end
Person.m

#import <Foundation/Foundation.h>
#import "Person.h"

//类实现部分,继承的书写类是可选的。
@implementation Person : NSObject

static int staticGlobalPersonNumber;

//所有以init开头的函数作为构造函数使用
-(id) init:(NSString *)firstname secondname:(NSString *)secondname
{
    if ( self = [super init] )
    {
        self.personFirstName = firstname;
        self.personLastName = secondname;
    }
    return self;
}

+(int) getPersonNumber
{
    //类方法不能访问实例属性,可以访问静态变量
    return staticGlobalPersonNumber;
}

//参数名字可以跟声明时不一样 声明时是first,second
-(void) setName:(NSString *)para1 sencondParaExtenalPara:(NSString *)para2
{
    //函数定义中操作的是para2,在调用的时候第二个参数需要加上sencondParaExtenalPara
    self.personFirstName = para1;
    self.personLastName = para2;
}

//函数重载 函数+label区别
-(void) setName:(NSString *)para1 second:(NSString *)para2
{
    //调用内部私有属性实现,注意这个标签是匿名的
    [self innerFunction:para1 :para2];
}
-(NSString *) getFirstName
{
    return _personFirstName;
}

-(NSString *) getLastName
{
    return _personFirstName;
}

//匿名标签的内部函数,只要在interface头文件中不声明,通过实例就不能调用
-(void)innerFunction:(NSString *)p1 :(NSString *)p2
{
    self.personFirstName = p1;
    self.personLastName = p2;
}
@end
main.m

#import <Foundation/Foundation.h> //C语言相同标准库<>,自己的头文件用“”
#import "Person.h"

//C语言中的一切都可以使用。
void func()
{
    printf("test\n");
}

int main(int argc, const char * argv[])
{
    func();
    
    @autoreleasepool // 被包含在这个括号内的新建对象会被自动释放
    {
        int test = 5;
        // %d 表示10进制数字,OC中新加了一个 %@ 表示对象。
        // %@属性再NSObject中实现,返回对象的地址或内存的地址,子类可以重载,
        // 比如NSString重载为返回字符串
        NSLog(@"test is :%d", test); //@的字符串为NSString类型
        
        
        //定义和初始化的方法
        Person *p = [Person alloc]; //分配内存
        p = [p init]; //初始化函数
        
        //也可以这样写
        // Person *p2 = [[Person alloc] init];
        
        //当然简单的方法还是有的
        // Person *p3 = [Person new];
        
        //这种函数调用方法,实在是很难适应
        [p setName: @"new" sencondParaExtenalPara:@"name"];
        
        //下面只有在类实现文件中定义了,没有在.h头文件中声明,所以不能在外部调用。
        //[p innerFunction: @"inner" :@"inner"]
        
        NSLog(@"%@", [p getLastName]);
        
        p = [p init:@"Firstname" secondname:@"SecondName"];
        NSLog(@"%@", [p getLastName]);
        
        //在以前需要手动释放alloc的对象,现在不需要了
        //[p release];
    }
    return 0;
}


//<完>

Swift与OC,C++混合编程

博文 来自: luthan
没有更多推荐了,返回首页