现在的位置: 首页 > 综合 > 正文

Nebula2探秘10-Signal System

2013年11月14日 ⁄ 综合 ⁄ 共 5423字 ⁄ 字号 评论关闭

Nebula2探秘10-Signal System

happykevins文     

使用Nebula2信号系统的目的:

  Nebula2的信号系统主要功能是对象间的消息传递。
  由于消息的发出者和接收者是在运行时动态邦定的,所以用这种方式传递消息并不会增加程序的耦合度。
  另外Nebula2还提供了一个SignalServer用于实现延时消息。

Nebula2信号系统主要包含以下几个类:
  nSignal:
   继承自nCmdProto类,用于标识一个信号,并描述信号回调函数的原形
  nSignalRegistry:
   包含多个nSignal的集合;nClass继承自此类;因此可以推测出信号是与类
   邦定的,要使Nebula类型支持产生信号,我们首先要向该类注册信号
  nSignalBinding:
   封装了信号接收者及其回调函数,用于向信号发出者注册
  nSignalBindingSet:
   包含多个nSignalBinding的集合
  nSignalEmitter:
   信号发生器,nObject继承自此类;因此所有的Nebula对象都支持发出信号
   的功能,前提是你注册了信号
  nSignalServer:
   这其实是独立于信号系统的一个附加功能,主要是实现了相应延时信号

Nebula2信号系统的使用方法:

  Nebula2的信号系统支持Native代码和脚本两种途径的传递,下面简单介绍通过脚本途径的使用。
  首先需要实现一个用于产生信号的Emtter类,Emitter就是一个普通的继承自nObject的Nebula2类型,只是在初始化命令的函数中添加了信号(nSignal)。
  然后我们需要实现一个Receiver类,Receiver类也是一个继承自nObject的普通Nebula2脚本类,可以将Receiver的脚本指令向Emitter中感兴趣的信号注册,这样在Emitter产生信号时就会向注册的Receiver广播消息了;需要注意的是在Receiver向Emitter注册时需要保证Receiver的回调函数与Emitter的信号的函数原形保持一致。

 Nebula2引擎的Bug:
  需要改正一个Nebula2的Bug,在nargs.h的第276行加上代码:
   this->type = Type::String;
  原来的代码由于缺少这句话,在nArgs从va_list复制String类型参数时会丢失类型信息,所以在信号传递过程中如果使用String类型参数的话Nebula2就会出错。

 下面是Emitter的代码:

/****************************************************************************/
/*    Nebula2 - Tutorial 10                                                    */
/*  Nebula2 Signal System                                                    */
/*  author: happykevins                                                        */
/****************************************************************************/

/// Emitter.h
#pragma once
#include 
"kernel/nroot.h"
#include 
"signals/nsignal.h"

class Emitter : public nRoot
{
    
/// @note
    
/// 为了支持信号系统,在类的实现中不需要添加任何代码
    
/// 只需在Emitter对应的nClass中注册信号即可
    
/// 注册信号的工作一般在初始化脚本指令的函数(n_initcmds)中完成
};

/// Emitter.cpp
#include "Emitter.h"
#include 
"kernel/nkernelserver.h"
#include 
"../NebulaUtils/nutildefs.h"

nNebulaScriptModule(Emitter, emitter, "nroot");

void nNebulaScriptInitCmds(emitter)(nClass* cls)
{
    
/// 在这里添加信号
    
/// 注册信号始需要指出信号对应回调函数的原形以及信号的ID
    cls->BeginSignals(1);
    cls
->AddSignal("v_sig1_s"'SIG1');
    cls
->EndSignals();
}

下面是Receiver的代码:

/****************************************************************************/
/*    Nebula2 - Tutorial 10                                                    */
/*  Nebula2 Signal System                                                    */
/*  author: happykevins                                                        */
/****************************************************************************/

/// Receiver.h
#pragma once
#include 
"kernel/nroot.h"

class Receiver: public nRoot
{
public:
    
void Print(const char* str)
    {
        n_printf(
"%s ", str);
    }
};

/// Receiver.cpp
#include "Receiver.h"
#include 
"kernel/nkernelserver.h"
#include 
"../NebulaUtils/nutildefs.h"

nNebulaScriptModule(Receiver, receiver, "nroot");

static void n_print(void* o, nCmd* cmd);

void nNebulaScriptInitCmds(receiver)(nClass* cl)
{
    
/// 为Emitter的回调添加脚本函数
    
/// 信号系统也是通过脚本函数来传递消息
    
/// 脚本函数的需要与Emitter对应的信号保持一致
    cl->BeginCmds();
    cl
->AddCmd("v_print_s"'PRNT', n_print);
    cl
->EndCmds();
}

static void n_print(void* o, nCmd* cmd)
{
    Receiver
* slf = (Receiver*)o;
    slf
->Print(cmd->In()->GetS());
}

下面是使用信号系统的范例代码:

/****************************************************************************/
/*    Nebula2 - Tutorial 10                                                    */
/*  Nebula2 Signal System                                                    */
/*  author: happykevins                                                        */
/****************************************************************************/

///----------------------------------------------------------------------------
/// +必要头文件

// nebula2 includes
#include "kernel/nkernelserver.h"
#include 
"kernel/ntimeserver.h"
#include 
"signals/nsignalserver.h"
#include 
"../NebulaUtils/nutildefs.h"

#include "Emitter.h"
#include 
"Receiver.h"

/// -必要头文件
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +声明使用的Nebula2 Package&Module
nNebulaUseModule(emitter);
nNebulaUseModule(receiver);
/// -声明使用的Nebula2 Package&Module
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +Application
int main(int argc, const char** argv)
{
    
/// 创建KernelServer
    nKernelServer* ks = n_new(nKernelServer);

    nNebulaAddModule(emitter);
    nNebulaAddModule(receiver);

    /// 创建SignalServer
    nSignalServer* signals = (nSignalServer*)ks->New("nsignalserver""/sys/servers/signals");

    /// 创建信号发生器
    Emitter* emit = (Emitter*)ks->New("emitter""/usr/signals/emitter");
    
/// 创建信号接收器
    Receiver* rec = (Receiver*)ks->New("receiver""/usr/signals/receiver");

    /// 将信号接收器邦定到信号发生器指定的信号
    emit->BindSignal('SIG1', rec, 'PRNT'0true);

    /// 发出立即信号
    emit->EmitSignal('SIG1'"Emit Signal Synchronized!");

    /// 发出延迟信号(5秒后执行)
    emit->PostSignal(5.0f'SIG1'"Emit Signal Asynchronized!");

    n_printf("*****Wait Asynchronized Signal***** ");
    
    
/// 等待延迟信号
    double time = 0;
    
while ( time  8.0f)
    {
        signals
->Trigger(nTimeServer::Instance()->GetFrameTime());
        n_sleep(
0.2f);
        time 
+= 0.2f;
    }

    n_printf("*****Press Any Key!***** ");

    /// 销毁KernelServer
    n_delete(ks);

    getchar();
    return 0;
}
/// -Application
///----------------------------------------------------------------------------

 

抱歉!评论已关闭.