与 C++ 合作iOS 中的 fuzzylite lib 和 ObjC(模糊逻辑)
我已经溜进了这里泳池的深处。我已经取得了一些不错的进步,但现在只是在挣扎。我正在尝试在 iOS 中使用这个模糊逻辑库: http://code.google.com /p/fuzzy-lite/
我已经编译它了 - 我所做的是添加 .cpp 和 .cpp 。将 .h 文件添加到我的项目中,并将主 viewController 上的后缀更改为“.mm”。我可以从 viewDidload 中运行 fuzzyLite test.h 文件(如下所示)。它运行并显示测试数据。
我需要做的是创建 fuzzyLite 的持久实例,以便我可以在我的应用程序中使用它(例如能够解决它,然后在应用程序卸载时进行清理)。
我已经四处搜索,但还没有理解在 ObjC 项目中包含 C++ 代码的讨论/示例。有人可以告诉我一种可以继续推进的方法 - 包装 fuzzyLite 代码,以便我可以调用函数并获取结果吗?谢谢!
编辑:我使用此处详细介绍的方法在这方面取得了进展: http://robnapier.net/blog/wrapping-c-take-2 -1-486
我不清楚的一件事是内存清理。 dealloc 函数清理了包装的 CPP 实例的实例 - 但是 CCP 实例内分配的内存又如何呢?似乎我需要在删除实例之前调用一个方法来释放它。
例如:包装的类有一些子类的实例变量 - 我的 cleanup 函数足以正确管理内存吗?
void Bingo::cleanup(){
delete engine;
engine = NULL;
delete health;
health = NULL;
delete energy;
energy = NULL;
}
-包装的 CPP 类的标头
#include "fuzzylite/FuzzyLite.h"
namespace fl {
class Bingo {
public:
FuzzyEngine* engine;
OutputLVar* health;
InputLVar* energy;
Bingo();
void Fuzz();
void setInput(float input);
};
}
来自 ObjC 包装器:
- (void)dealloc
{
delete _cpp;
_cpp = NULL;
[super dealloc];
}
FuzzyLiteIOSViewController.mm
#include "FuzzyLiteIOSViewController.h"
#include "FuzzyLite.h"
#include "test.h"
#include <limits>
#include "fuzzylite/FunctionTerm.h"
//stuff not shown
- (void)viewDidLoad
{
[super viewDidLoad];
fl::Test* test = new fl::Test();
test->SimpleMamdani();
}
test.h
#ifndef FL_TEST_H
#define FL_TEST_H
namespace fl {
class Test {
public:
static void SimpleMamdani();
};
}
#endif /* FL_TEST_H */
test .cpp
#include "fuzzylite/test.h"
#include "fuzzylite/FuzzyLite.h"
#include <limits>
#include "fuzzylite/FunctionTerm.h"
namespace fl {
void Test::SimpleMamdani() {
FuzzyOperator& op = FuzzyOperator::DefaultFuzzyOperator();
FuzzyEngine engine("simple-mamdani", op);
engine.hedgeSet().add(new fl::HedgeNot);
engine.hedgeSet().add(new fl::HedgeSomewhat);
engine.hedgeSet().add(new fl::HedgeVery);
fl::InputLVar* energy = new fl::InputLVar("Energy");
energy->addTerm(new fl::ShoulderTerm("LOW", 0.25, 0.5, true));
energy->addTerm(new fl::TriangularTerm("MEDIUM", 0.25, 0.75));
energy->addTerm(new fl::ShoulderTerm("HIGH", 0.50, 0.75, false));
engine.addInputLVar(energy);
fl::OutputLVar* health = new fl::OutputLVar("Health");
health->addTerm(new fl::TriangularTerm("BAD", 0.0, 0.50));
health->addTerm(new fl::TriangularTerm("REGULAR", 0.25, 0.75));
health->addTerm(new fl::TriangularTerm("GOOD", 0.50, 1.00));
engine.addOutputLVar(health);
fl::RuleBlock* block = new fl::RuleBlock();
block->addRule(new fl::MamdaniRule("if Energy is LOW then Health is BAD", engine));
block->addRule(new fl::MamdaniRule("if Energy is MEDIUM then Health is REGULAR", engine));
block->addRule(new fl::MamdaniRule("if Energy is HIGH then Health is GOOD", engine));
engine.addRuleBlock(block);
for (fl::flScalar in = 0.0; in < 1.1; in += 0.1) {
energy->setInput(in);
engine.process();
fl::flScalar out = health->output().defuzzify();
(void)out; //Just to avoid warning when building
FL_LOG("Energy=" << in);
FL_LOG("Energy is " << energy->fuzzify(in));
FL_LOG("Health=" << out);
FL_LOG("Health is " << health->fuzzify(out));
FL_LOG("--");
}
}
I've wandered into the deep end of the pool here. I've made some good progress but now am just thrashing around. I'm trying to use this fuzzy logic lib in iOS: http://code.google.com/p/fuzzy-lite/
I've got it to compile - what I did was to add both the .cpp & the .h files to my project and changed the suffix on my main viewController to ".mm". I am able to run the fuzzyLite test.h file from within viewDidload (show below). It runs and the test data is displayed.
What I need to do is create a persistent instance of fuzzyLite so I can use it in my app (e.g. be able to address it and then clean up when the app unloads).
I've searched around but haven't understood the discussions/examples of including C++ code in an ObjC project. Can someone show me a way I can move forward with this - wrapping the fuzzyLite code so I can call functions and get results back? Thanks!
EDIT: I've made progress on this using the method detailed here:
http://robnapier.net/blog/wrapping-c-take-2-1-486
One thing I am unclear on is memory cleanup. The dealloc function cleans up the instance of the wrapped CPP instance - but what about memory alloc'ed within the CCP instance? Seems like I need call a method to release that prior to deleting the instance.
ex: the wrapped class has some instance vars of subclasses- is my cleanup function enough to manage the memory properly?
void Bingo::cleanup(){
delete engine;
engine = NULL;
delete health;
health = NULL;
delete energy;
energy = NULL;
}
-header for the wrapped CPP class
#include "fuzzylite/FuzzyLite.h"
namespace fl {
class Bingo {
public:
FuzzyEngine* engine;
OutputLVar* health;
InputLVar* energy;
Bingo();
void Fuzz();
void setInput(float input);
};
}
from the ObjC wrapper:
- (void)dealloc
{
delete _cpp;
_cpp = NULL;
[super dealloc];
}
FuzzyLiteIOSViewController.mm
#include "FuzzyLiteIOSViewController.h"
#include "FuzzyLite.h"
#include "test.h"
#include <limits>
#include "fuzzylite/FunctionTerm.h"
//stuff not shown
- (void)viewDidLoad
{
[super viewDidLoad];
fl::Test* test = new fl::Test();
test->SimpleMamdani();
}
test.h
#ifndef FL_TEST_H
#define FL_TEST_H
namespace fl {
class Test {
public:
static void SimpleMamdani();
};
}
#endif /* FL_TEST_H */
test.cpp
#include "fuzzylite/test.h"
#include "fuzzylite/FuzzyLite.h"
#include <limits>
#include "fuzzylite/FunctionTerm.h"
namespace fl {
void Test::SimpleMamdani() {
FuzzyOperator& op = FuzzyOperator::DefaultFuzzyOperator();
FuzzyEngine engine("simple-mamdani", op);
engine.hedgeSet().add(new fl::HedgeNot);
engine.hedgeSet().add(new fl::HedgeSomewhat);
engine.hedgeSet().add(new fl::HedgeVery);
fl::InputLVar* energy = new fl::InputLVar("Energy");
energy->addTerm(new fl::ShoulderTerm("LOW", 0.25, 0.5, true));
energy->addTerm(new fl::TriangularTerm("MEDIUM", 0.25, 0.75));
energy->addTerm(new fl::ShoulderTerm("HIGH", 0.50, 0.75, false));
engine.addInputLVar(energy);
fl::OutputLVar* health = new fl::OutputLVar("Health");
health->addTerm(new fl::TriangularTerm("BAD", 0.0, 0.50));
health->addTerm(new fl::TriangularTerm("REGULAR", 0.25, 0.75));
health->addTerm(new fl::TriangularTerm("GOOD", 0.50, 1.00));
engine.addOutputLVar(health);
fl::RuleBlock* block = new fl::RuleBlock();
block->addRule(new fl::MamdaniRule("if Energy is LOW then Health is BAD", engine));
block->addRule(new fl::MamdaniRule("if Energy is MEDIUM then Health is REGULAR", engine));
block->addRule(new fl::MamdaniRule("if Energy is HIGH then Health is GOOD", engine));
engine.addRuleBlock(block);
for (fl::flScalar in = 0.0; in < 1.1; in += 0.1) {
energy->setInput(in);
engine.process();
fl::flScalar out = health->output().defuzzify();
(void)out; //Just to avoid warning when building
FL_LOG("Energy=" << in);
FL_LOG("Energy is " << energy->fuzzify(in));
FL_LOG("Health=" << out);
FL_LOG("Health is " << health->fuzzify(out));
FL_LOG("--");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据所提供的信息基本上无法回答您的问题。您的问题是关于
Bingo
类的cleanup
方法,但是 Bingo 的实例(无论是在堆栈上还是在堆上)都不会出现在您的代码摘录中。同样,您声明您正在清理“包装的 CPP 实例”,但在其他地方没有引用它。看起来确实在您的Test::SimplMamdani
方法中存在泄漏——您new
了一堆不[at至少在显示的代码中]有任何相应的删除。同样,在您的 FuzzyLiteIOSViewController::viewDidLoad 方法中,您在堆上创建一个 Test 实例,而没有相应的删除。我假设你的 C++ 代码中没有 autoptr 的东西。已更新以提供附加信息:
根据您的评论,您需要回顾 C++ 的基本语言结构。基本规则是您需要
删除
您新建
的任何内容。 Bingo 类的清理应该在析构函数(Objective-C 的 dealloc 的 C++ 构造)中执行。您的Bingo
类应该看起来更像:Bingo.h:
Bingo.cpp:
当您
删除
Bingo 实例时,将调用析构函数,并且Bingo
code> 的成员变量将被释放。可以说,您的成员变量(引擎、健康和能量)应该在范围内是私有的,并通过公共范围的 getter 和 setter 来公开。
获取 Bjarne Stroustrup 的 C++ 参考的副本并快速阅读,或者使用在线入门指南,例如
It's basically not possible to answer your question given the information provided. Your question is about the
cleanup
method of theBingo
class, but instances of Bingo (either on the stack or the heap) appear nowhere in your code excerpts. Likewise, you state that you are cleaning up a "wrapped CPP instance" but it's referenced nowhere else. It does appear that you have leaks in yourTest::SimplMamdani
method -- younew
a bunch of objects there that don't [at least in the revealed code] have any correspondingdelete
s. Similarly, in yourFuzzyLiteIOSViewController::viewDidLoad
method you create aTest
instance on the heap without a correspondingdelete
. I'm assuming that there's no autoptr stuff going on under the hood in your C++ code.UPDATED to provide additional information:
Based upon your comment, you need to review the basic language structure of C++. The basic rule is that you'll need to
delete
anything that younew
. Clean up for theBingo
class should be performed in the destructor (a C++ construct to Objective-C'sdealloc
). YourBingo
class should look something more like:Bingo.h:
Bingo.cpp:
When you
delete
a Bingo instance, the destructor will be called andBingo
's member variables will be disposed.Arguably your member variables (engine, health, and energy) should be private in scope and exposed via public-scoped getters and setters.
Grab a copy of Bjarne Stroustrup's C++ reference and give it a quick perusal, or use an online get-up-and-going guide like this one.