65.9K
CodeProject 正在变化。 阅读更多。
Home

Kigs框架介绍 (4/8) - 方法

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.55/5 (7投票s)

2020年2月13日

MIT

2分钟阅读

viewsIcon

12317

一个多用途、跨平台、免费且开源的C++框架。本文将重点介绍CoreModifiable方法。

Kigs Logo

目录

引言

查看 已在此系列中发布 部分以了解之前的内容。

在本文中,我们将重点介绍CoreModifiable方法。CoreModifiable方法是可以按名称调用的方法,无需知道被调用实例的确切类型。

快速访问固定原型方法

固定原型是

bool    methodName(CoreModifiable* sender,
        std::vector<CoreModifiableAttribute*>& params,void* privateParams);

参数是

  • CoreModifiable* sender: 调用者类
  • std::vector<CoreModifiableAttribute*>& params: CoreModifiableAttribute*参数的vector
  • void* privateParams: 一个可能的用户定义的私有参数

返回值是bool值。返回值的含义由用户定义。

可以使用帮助宏来声明成员方法:DECLARE_METHODDECLARE_VIRTUAL_METHODDECLARE_PURE_VIRTUAL_METHODDECLARE_OVERRIDE_METHOD

// declare member method called "GiveInfos"
DECLARE_METHOD(GiveInfos);

然后必须使用COREMODIFIABLE_METHODS来列出使用前一个辅助宏之一声明的所有方法(或直接使用CoreModifiable方法原型)

// list all CoreModifiable methods
COREMODIFIABLE_METHODS(GiveInfos);

然后使用辅助宏DEFINE_METHOD来定义方法

// define member method named GiveInfos on SimpleClass
DEFINE_METHOD(SimpleClass, GiveInfos)
{
    
    std::cout << "SimpleClass GiveInfos method called on 
                 " << getName() << " instance" << std::endl;
    std::cout << "-- sender : " << sender->getName() << std::endl;

    for (auto p : params)
    {
        std::string v;
        if (p->getValue(v,this))
        {
            std::cout << "-- parameter : " << p->id() << 
                         " value is : " << v << std::endl;
        }
        else
        {
            std::cout << "-- parameter : " << p->id() << 
                         " value cannot be evaluated as string" << std::endl;
        }
    }

    if(privateParams)
        std::cout << "-- private parameter is not null" << std::endl;
    else
        std::cout << "-- private parameter is null" << std::endl;

    return true;
}

快速调用

然后可以使用“CallMethod”调用方法,如下所示

// create dynamic attribute on this
AddDynamicAttribute<maFloat, float>("FloatParam", 12.0f);

// create CoreModifiableAttribute without owner
CoreModifiableAttribute* intParam = new maInt("IntParam", 15);

// create a parameter vector
std::vector<CoreModifiableAttribute*> params;
// push dynamic attribute "FloatParam" on vector
params.push_back(getAttribute("FloatParam"));
// push intParam
params.push_back(intParam);
    
// call GiveInfos on instance1 with params vector, private parameter and sender are nullptr  
bool result = instance1->CallMethod("GiveInfos", params, nullptr, nullptr);
std::cout << "GiveInfos returns " << (result?"true":"false") << std::endl << std::endl;

较慢的简单调用

SimpleCall模板方法自动将参数编码到向量中

// "SimpleCall" on instance2:
result = instance2->SimpleCall("GiveInfos", 32,64,5);
std::cout << "GiveInfos returns " << (result ? "true" : "false") << std::endl << std::endl;

返回值

可以使用辅助宏PUSH_RETURN_VALUE将返回值推入参数向量中。
使用CallMethod调用时,必须在调用后删除返回值和分配的参数(否则将发生内存泄漏)。

// call GiveInfos on instance2 with params vector, private parameter and sender are nullptr   
int paramsCount = params.size();
result = instance2->CallMethod("GiveInfos", params, nullptr, nullptr);
if (params.size() > paramsCount)
{
    // return values added
    while(paramsCount<params.size())
    {
        std::string v;
        if(params.back()->getValue(v,this))
            std::cout << "GiveInfos returned value = " << v << std::endl;

        delete params.back();
        params.pop_back();
    }
}
std::cout << "GiveInfos returns " << (result ? "true" : "false") << std::endl << std::endl;

使用SimpleCall,可以使用模板参数自动管理返回值

// "SimpleCall" on instance2:
float floatresult = instance2->SimpleCall<float>("GiveInfos", 32,64,5);
std::cout << "GiveInfos returns " << floatresult << std::endl << std::endl;

较慢的访问包装方法

任何成员方法都可以包装为CoreModifiable方法。在类声明中

float Multiply(float v1, float v2)
{
    return v1 * v2;
}
// Multiply method can be called with SimpleCall
WRAP_METHODS(Multiply);

然后可以这样调用Multiply方法

float floatresult = instance2->SimpleCall<float>("Multiply", 32, 5);
std::cout << "instance2 Multiply returns " << floatresult << std::endl << std::endl;

动态方法

CoreModifiable继承的实例可以使用动态方法进行增强。

可以这样定义动态方法

// declare a dynamic method named addValues which can be added to any CoreModifiable instance
DEFINE_DYNAMIC_METHOD(CoreModifiable, addValues)
{
    float result = 0.0f;
    for (auto p : params)
    {
        float v;
        if (p->getValue(v,this))
        {
            result += v;
        }
    }
    PUSH_RETURN_VALUE(result);
    return true;
}

然后在运行时,将此方法添加到给定的实例,并使用SimpleCall调用它

// now add addValues method on instance2, calling name is also addValues
instance2->INSERT_DYNAMIC_METHOD(addValues, addValues);
floatresult = instance2->SimpleCall<float>("addValues", 32, 5);
std::cout << "instance2 addValues returns " << floatresult << std::endl << std::endl;

此机制可用于使用特定行为来修饰实例。

在Sample4项目(浏览代码)中查找本文中的所有示例代码。

已在此系列中发布

  1. Kigs框架介绍 (1/8) - 概述
  2. Kigs框架介绍 (2/8) - CoreModifiable
  3. Kigs框架介绍 (3/8) - 属性
  4. Kigs框架介绍 (4/8) - 方法
  5. Kigs框架介绍 (5/8) - CoreItem
  6. Kigs框架介绍 (6/8) - 信号,槽,通知
  7. Kigs框架介绍 (7/8) - Lua绑定
  8. Kigs框架介绍 (8/8) - 数据驱动应用程序

历史

  • 2020年2月13日:初始版本
  • 2020年2月21日:文章 (5/8) 添加到该系列
  • 2020年3月3日:文章 (6/8) 添加到该系列
  • 2020年3月19日:文章 (7/8) 添加到该系列
  • 2020年6月17日:添加了该系列的最后一篇文章
  • 2023年3月1日:框架重构后文章更新
© . All rights reserved.