我有一个从工业 Controller 读取过程数据数组的应用程序。我想在数据发生变化时将该数据推送到网页。为此,我用 C++ 编写了一个 node.js 插件,用于扫描流程数据并尝试在数据值更改时触发事件。在 Addon 尝试触发事件之前一切正常,此时 node.js 终止并出现错误:
undefined:0
TypeError: undefined is not a function
CPP、javascript shim 和测试 javascript 如下。非常感谢任何见解。
提前致谢。
Node 核心链接.cpp
typedef struct CoreLinkValue
{
// pointer to a CTS variant value
CtsVariant* value;
// copy of the last value that was broadcast
CtsVariant lastValue;
} CoreLinkValue;
//
// An event structure for pushing events to node.js
// Requires the javascript shim code in node_corelink.js
//
struct Emitter: ObjectWrap
{
static Handle<Value> New(const Arguments& args);
static Handle<Value> DataChange(const char* topic, CtsVariant* value);
};
//
// Create a message payload based on the variant type and
// initiate sending out on the topic
//
static Handle<Value>
createVariantHandle(CtsVariant* value)
{
Handle<Value> ret;
switch (value->type)
{
case CTSTYPE_BIT:
case CTSTYPE_BYTE:
ret = Integer::New(value->value.byte[0]);
break;
case CTSTYPE_WORD:
ret = Integer::New(value->value.word[0]);
break;
case CTSTYPE_DWORD:
ret = Integer::New(value->value.dword[0]);
break;
case CTSTYPE_WORD64:
ret = Number::New(value->value.word64);
break;
case CTSTYPE_REAL64:
ret = Number::New(value->value.real64);
break;
default:
ret = Undefined();
break;
}
return ret;
}
Handle<Value> Emitter::New(const Arguments& args)
{
HandleScope scope;
assert(args.IsConstructCall());
Emitter* self = new Emitter();
self->Wrap(args.This());
return scope.Close(args.This());
}
// emits DataChange Event
Handle<Value> Emitter::DataChange( const char* topic, CtsVariant* value )
{
HandleScope scope;
Handle<Value> argv[3] = {
String::New("DataChange"), // event name
String::New(topic), // topic argument
createVariantHandle(value) // value argument
};
printf ("C++ Emitting event!\n" );
MakeCallback(context_obj_, "emit", 2, argv);
return True();
}
//
// Triggered by the event loop on a regular interval.
// Scans the registered data to see if the latest value has been
// broadcast and does so if needed.
//
void
scan_task( uv_timer_t* timer, int status )
{
std::map<std::string, CoreLinkValue>::iterator it;
bool doUpdate;
for( it = pdos_.begin();
it != pdos_.end();
++it )
{
if (forceRefreshPdos_ == true)
{
//
// An update of this value was requested.
//
doUpdate = true;
}
else if ( it->second.value->type != it->second.lastValue.type )
{
//
// If the types don't match, then this variant was obviously
// updated.
//
doUpdate = true;
}
else if ( it->second.value->value.word64 != it->second.lastValue.value.word64 )
{
//
// Word64 contains all bits of the value. If this value has
// changed, then they've all changed.
//
doUpdate = true;
}
else
{
doUpdate = false;
}
if (doUpdate)
{
it->second.lastValue.value = it->second.value->value;
Emitter::DataChange( it->first.c_str(), it->second.value );
}
}
if (forceRefreshPdos_)
{
forceRefreshPdos_ = false;
printf("Completed refresh all.\n");
}
}
//
// Start the execution of the scan loop
//
int
startScanLoop( void )
{
uv_timer_init( uv_default_loop(), &scanTimer_ );
uv_timer_start(
&scanTimer_, // timer instance
&scan_task, // callback function
0, // startup delay (ms)
100 ); // repeat interval (ms)
return 1;
}
//
// Stop the execution of the scan loop
//
void
stopScanLoop( void )
{
uv_timer_stop( &scanTimer_ );
}
//
// Connects to the kernel IPC
//
Handle<Value>
connect(const Arguments& args)
{
HandleScope scope;
...
startScanLoop();
return scope.Close( True() );
}
//
// Shuts down the kernel IPC
//
Handle<Value>
close(const Arguments& args)
{
HandleScope scope;
stopScanLoop();
...
return scope.Close( True() );
}
//
// Called by node.js to initialize the library.
//
void
init(Handle<Object> target)
{
target->Set(String::NewSymbol("connect"),
FunctionTemplate::New(connect)->GetFunction());
target->Set(String::NewSymbol("close"),
FunctionTemplate::New(close)->GetFunction());
//
// Events interface
//
Local<FunctionTemplate> t = FunctionTemplate::New(Emitter::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(String::New("Emitter"));
target->Set(String::NewSymbol("Emitter"), t->GetFunction());
}
NODE_MODULE(node_corelink, init)
node_corelink.js
module.exports = require(__dirname + '/build/Release/node_corelink.node');
var Emitter = require(__dirname + '/build/Release/node_corelink.node').Emitter;
var events = require('events');
inherits(Emitter, events.EventEmitter);
exports.Emitter = Emitter;
// extend prototype
function inherits(target, source) {
for (var k in source.prototype)
target.prototype[k] = source.prototype[k];
}
测试.js
process.stdin.resume(); //so the program will not close instantly
process.on('exit', function () {
corelink.close();
console.log('Goodbye!');
});
process.on('SIGINT', function () {
console.log('Got SIGINT.');
process.exit();
});
var corelink = require('./node_corelink');
var Emitter = require('./node_corelink').Emitter;
var e = new Emitter();
e.on('DataChange', function(s) {
console.log('DataChange');
});
corelink.connect();
最佳答案
我能够以不太优雅的方法触发回调。
node_corelink.js
module.exports = require(__dirname + '/build/Release/node_corelink.node');
测试.js
var corelink = require('./node_corelink');
function onDataChange( topic, value )
{
if ( value !== undefined )
console.log ( topic + " ::: " + value.toString() );
}
function onMessage( msg )
{
console.log ( "Message from kernel: " + msg.toString() );
}
corelink.connect(onDataChange, onMessage);
Node 核心链接.cpp
static void
dataChange( const char* topic, CtsVariant* value )
{
HandleScope scope;
Handle<Value> argv[2] =
{
String::New(topic), // topic argument
createVariantHandle(value) // value argument
};
MakeCallback(Context::GetCurrent()->Global(), pfOnDataChange_, 2, argv);
}
static void
onMessage( const char* message )
{
HandleScope scope;
Handle<Value> argv[1] =
{
String::New(message) // message argument
};
MakeCallback(Context::GetCurrent()->Global(), pfOnMessage_, 1, argv);
}
//
// Connects to the kernel IPC
//
Handle<Value>
connect(const Arguments& args)
{
HandleScope scope;
if ( args.Length() < 2
|| !args[0]->IsFunction()
|| !args[1]->IsFunction() )
{
return scope.Close( False() );
}
pfOnDataChange_ = Persistent<Function>::New(args[0].As<Function>());
pfOnMessage_ = Persistent<Function>::New(args[1].As<Function>());
...
return scope.Close( True() );
}
关于javascript - 在 Node.js C++ 插件中发出事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19231174/
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的