I'm a newer to NPAPI. I come across one problem.
in my plugin, I need to return some data from C++ to JavaScript, yes,that's callback. but the callback thread and the main thread are separate threads. So I use NPN_PluginThreadAsyncCall, but the problem can not be solved also. When callback, the firefox crashed...
Can anyone help me?
the bellow codes are in the callback thread, Can anyone tell me, why it crashed?
npnfuncs->pluginthreadasynccall(instance,callBackfunc,(void*)pdata);
/////////////////////////////////////////////////////////////////////
void callBackfunc(void* arg)
{
NPObject *winobj;
npnfuncs->getvalue(instance,NPNVWindowNPObject,&winobj);
NPVariant handler;
NPIdentifier id1 = npnfuncs->getstringidentifier("MyTest".c_str());
npnfuncs->getproperty(instance, winobj, id1, &handler);
NPObject* handlerObj= NPVARIANT_TO_OBJECT(handler);
NPVariant prototype;
NPIdentifier id2 = npnfuncs->getstringidentifier("prototype");
npnfuncs->getproperty(instance, serviceHandlerObj, id2, &prototype);
NPObject* prototypeObj= NPVARIANT_TO_OBJECT(prototype);
NPIdentifier id = npnfuncs->getstringidentifier("fun".c_str());
NPVariant voidResponse;
int status=npnfuncs->invoke(instance,prototypeObj,id,args,argCount,&voidResponse);
return;
}
thanks
Best Regards
greatsea
... What is "MyTest".c_str() supposed to be? This is C++, no? c_str() is a method of a std::string class, and I don't see that being sued here, so trying to do a .c_str() on it shouldn't even compile, unless there is something going on here that I really don't understand.
Also be aware that at least Safari 5.1 has stopped supporting NPN_PluginThreadAsyncCall and different methods need to be used to make cross-thread callbacks. I don't know if other browsers have or will or not; so far it doesn't seem so.
Is there a reason you're not just using FireBreath for your plugin? It solves all of these problems for you and lets you just focus on your plugin...
Related
Apache Thrift is one of the more popular choices for an opensource RPC frameworks (gRPC is also one that gets lot of tracktion since release into the open).
In my setup in c++ Im using a TMultiplexedProcessor. I guess this could be any TProcessor for that matter since Im just interested in printing whatever is sent.
This has a method called:
bool process(std::shared_ptr<protocol::TProtocol> in,
std::shared_ptr<protocol::TProtocol> out,
void* connectionContext) override {
My idea was to override this again, so that I could print the in argument - but how can I write TProtocol to output ? (at a glance, it does not seem straightforward to serialize into a string)
I get a feeling there maybe is some other or an easier method. So my question is how can I dump all messages recieved via thrift (for debugging purpose) ?
There's TProtocolTap and TDebugProtocol.
Usage example can be found in thrift_dump.cpp:
shared_ptr<TProtocol> iprot(new TBinaryProtocol(itrans));
shared_ptr<TProtocol> oprot(
new TDebugProtocol(
shared_ptr<TTransport>(new TBufferedTransport(
shared_ptr<TTransport>(new TFDTransport(STDOUT_FILENO))))));
TProtocolTap tap(iprot, oprot);
std::string name;
TMessageType messageType;
int32_t seqid;
for (;;) {
tap.readMessageBegin(name, messageType, seqid);
tap.skip(T_STRUCT);
tap.readMessageEnd();
}
I've been trying to get a persistent object from a thread for hours.
I want to write a shared library in C++ that starts a persistent loop in a function.
In the following code snippets there is a class called Process. Process initializes a TCP/IP interface to read and write data from a Simulink model.
This is only for declaration and should not be important for this problem, but now you know what I talk about when mentioning the processes.
main.cpp
I know, it looks kinda ugly/unprofessional, but I'm fairly new to C++..
// frustrated attempt to make everything persistent
static vector<std::thread> processThreads;
static ProcessHandle processHandle;
static vector<std::promise<Process>> promiseProcess;
static vector<std::future<Process>> futureProcess;
EXPORT int initializeProcessLoop(const char *host, int port)
{
std::promise<Process> promiseObj;
futureProcess.push_back(std::future<Process>(promiseObj.get_future()));
processThreads.push_back(std::thread(&ProcessHandle::addProcess, processHandle, host, port, &promiseProcess[0]));
Process val = futureProcess[0].get();
processHandle.handleList.push_back(val);
return (processHandle.handleList.size() - 1);
}
ProcessHandle.cpp
The addProcess function from ProcessHandle creates the Process that should be persistent, adds it to a static vector member of ProcessHandle and passes the promise to the execution loop.
int ProcessHandle::addProcess(const char *address, int port, std::promise<Process> * promiseObj) {
Process process(address, port);
handleList.push_back(process);
handleList[handleList.size() - 1].exec(promiseObj);
return handleList.size() - 1;
}
To the main problem now...
If I change "initializeProcessLoop" to include:
if(processHandle.handleList[0].isConnected())
{
processHandle.handleList[0].poll("/Compare To Constant/const");
}
after i've pushed "val" to the processHandle.handleList everything works fine and I can poll the data as it should be.
If I instead poll it from - for examle - the main function, the loop crashes inside of the "initializeProcessLoop" because "Process val" is reassigned (?) with futureProcess[0].get().
How can I get the Process variable and the threaded loop to be consistent after the function returns?
If there are any questions to the code (and I bet there will be), feel free to ask. Thanks in advance!
PS: Obligatory "English is not my native language, please excuse any spelling errors or gibberish"...
Okay, first I have to declare, that the coding style above and following are by any means not best practice.
While Sam Varshavchik is still right with how to learn C++ the right way, just changing
Process val = futureProcess[0].get();
to
static Process val = futureProcess[0].get();
did the job.
To be clear: don't do this. It's a quick fix but it will backfire in the future. But I hope that it'll help anyone with a similar problem.
If anyone has a better solution (it can't get any worse, can it?), feel free to add your answer to this question.
Currently, I'm working on compiling old .cpp classes under C++ Builder XE. Apart from many troubles, there is one which I have completely no idea how to solve.
My code:
String txt = "<Not so long sql query>";
int licz = some_function(txt, dzeFDS); //1
//assigning licz to somewhere
txt = "<much longer query>";
licz = some_function(txt, budFDS); //2
Problem is that during second call of some_function program is stopped and i have this alert:
First chance exception at $75A1C42D. Exception class EDatabaseError with message 'budFDS: Type mismatch for field 'Function', expecting: String actual: WideString'. Process Call.exe (1896)
It's strange form be, bacause first call of some_function works fine, but this second one (with arguments with the same type) doesn't.
some_function code:
int __fastcall some_function(String txt, TIBDataSet *firDS)
{
firDS->Close();
firDS->SelectSQL->Text = txt;
firDS->Open(); //during debugging, exception occurs in this line
int count = 0;
while(!firDS->Eof)
{ count++;
firDS->Next();
}
return count;
}
Any ideas what why it happens?
Thanks in advance
There is much pain in your future.
Anyway, the problem you're having is with the database connection. There's a field in your database called "Function" that holds a string. This field came across as a String with the ancient database driver that this program originally used. Your shiny, new database driver is telling VCL to expect such things as Unicode, and VCL doesn't like to shove such things into plain Strings, so it expects you to have a WideString ready in which to shove it.
Fortunately, there are ways of beating VCL into submission. What you want to do, since you surely don't want to rewrite half the application by changing TIBDataSet, is to tell the connection not to bother with Unicode. In order to do this, you have to set up the TSQLConnection object with UseUnicode=false, which I hope (I have no way of testing VCL code anymore) should look something like this:
connection->Params->Add("UseUnicode=false");
Where connection is the TSQLConnection object. I think you have to do this before connecting to the database.
If that doesn't work, see if you can configure the database driver to not use Unicode.
Problem solved - this one field Function has other type in C++ Builder design view - it was TStringField, and rest fields has TIBStringField...
I am trying to use an ActiveX control in my program.
QAxWidget* mAX = new QAxWidget();
mAX->setControl("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}");
I know that there is a function:
put_ChannelType(long newValue)
But when I try to execute it:
mAX->dynamicCall("put_ChannelType(long)",2);
mAX->dynamicCall("put_ChannelType(int)",2);
mAX->dynamicCall("put_ChannelType(long)",QVariant(2));
mAX->dynamicCall("put_ChannelType(int)",QVariant(2));
I get:
QAxBase: Error calling IDispatch member put_ChannelType: Bad parameter count
Any idea what is going wrong ?
EDIT:
Weird thing is if I call
mAX->dynamicCall("put_ChannelType()");
I do not get any error message...
EDIT 2:
This also fails (as Constantin suggested)
QList<QVariant> varlist;
varlist << (int)1;
mAX->dynamicCall("put_ChannelType(int)",varlist);
Got this solved using the generateDocumentation() function.
I was using this ActiveX control in another application, but an MFC one.
It seems the function names I was referring to (which were in a machine generated IDispatch wrapper class created by VS) were not the same as the ones Qt listed.
i.e. put_ChannelType is actually SetChannelType...
Maybe this is just a version issue ?
Anyways, important part is knowing that generateDocumentation() can list you all the functions you can call with dynamicCall.
Is it OK?
mAX->dynamicCall("put_ChannelType(const QVariant &)", (long)2);
I see that Qt has future class that is direct analog for boost::future but what is qt for boost::promise?
Constructing my own QFuture as shown in the accepted answer did not work for me. At first it seemed like it was working, but in my testing I realized it was not blocking the caller. Whoops! So I dug into the code a little further and found that QFutureInterface is what you want to use as your 'promise'. Like boost::promise, QFutureInterface is what you interact with in your worker thread, and it is a factory for QFutures.
So here's what I've been doing in Qt 4.8 (not sure if this is applicable to later versions).
QFutureInterface<QVariant> promise;
promise.reportStarted();
...
promise.reportResult(someVariant);
promise.reportFinished();
Then in the client thread, assuming you have access to the QFutureInterface 'promise'
QVariant result = promise.future().result();
The future() call is a factory method for creating a QFuture bound to your QFutureInterface. You should be able to get the QFuture and call result() on it later if you wanted.
The boost::promises are means of setting values in futures. In Qt, you can't set futures, you can only return them. That's the only way of "setting" data in a future.
So, in order to set data on a future, you have to return it from a function that was invoked by QtConcurrent::run. To do this, you'd use any of Qt's mechanisms for communicating between threads -- events, mutex-protected variables, etc. You have to tell the thread that runs the code that would return a future that given future is to be returned. That's the only way of achieving what a promise would do.
Alas, if you want to go into the undocumented territory, then the following code does what boost::promise::setValue would:
QFuture<int> f;
int i = 1;
...
f.d.reportResult(&i);
// or
f.d.reportFinished(&i);
I haven't bothered checking if it works (yet).
There is no official Qt analog but there are a few community libraries implementing promises (or similar patterns):
Ben Lau's AsyncFuture (benlau/asyncfuture)
Based on the undocumented QFutureInterface mentioned in one of the other answers.
And it's not exactly a promise pattern but rather an observer pattern.
Benoit Walter's QtPromise (bwalter/qt-promise)
Partially based on Ben Lau's AsyncFuture.
Simon Brunel's QtPromise (simonbrunel/qtpromise)
My QtPromise (julrich/QtPromise)
Disclaimer: I'm the author.
Promises for Qt are now also available with QML/JavaScript btw: https://v-play.net/updates/release-2-18-1-javascript-promises-for-rest-services-tinder-swipe-material-cards-qml-qsortfilterproxymodel-qml-youtube-player
Here is some example code:
import VPlayApps 1.0
import QtQuick 2.0
App {
Component.onCompleted: {
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = HttpRequest
.get("http://httpbin.org/get")
.then(function(resp) {
return resp.body;
});
var p4 = Promise.all([p1, p2, p3]);
p4.then(function(values) {
console.log(values[0]); // 3
console.log(values[1]); // 1337
console.log(values[2]); // resp.body
});
}
}
I created this library that is highly integrated with Qt and implements javascript-like promises:
https://github.com/juangburgos/QDeferred
It allows to create a thread-safe async API as follows:
multiplyNumbersInThread(3, 4)
.fail([](int res) {
Q_UNUSED(res);
qDebug() << "multiplyPositiveNumbers failed!";
})
.done([](int res) {
qDebug() << "multiplyPositiveNumbers succeded! Result :" << res;
});
Hope you find it useful.