How do I use FRESetContextNativeData() in AIR native extensions? - c++

I'm building an ANE. In one of my calls into native code, there's an object that gets created, and I'd like to be able to keep that in memory to reference in a future call.
I thought I could could do this by creating a pointer to the object, and then passing that pointer to FRESetContextNativeData() as in the example below:
FREObject storeData(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
char* data = "testing...";
FRESetContextNativeData( ctx, &data );
return getFREString(data);
}
FREObject retrieveData(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
char* data;
FREGetContextNativeData(ctx, (void**)&data);
return getFREString(data);
}
This doesn't seem to work however. At the end of retrieveData(), data points to a bunch of randomness. What gives?

So I'm a bit of an idiot. The mistake I made was putting & before data in my call to FRESetContextNativeData(). That one just needs a pointer, not a pointer to a pointer like FREGetContextNativeData().
The following code produces the results I was expecting:
FREObject storeData(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
char* data = "testing..."
FRESetContextNativeData( ctx, (void*)data );
return getFREString(data);
}
FREObject retrieveData(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
char *data;
FREGetContextNativeData(ctx, (void**)&data);
return getFREString(data);
}

Related

Isn't qualifier upcast/upgrade automatic? [duplicate]

Why my compiler(GCC) doesnt implicitly cast from char** to const char**?
Thie following code:
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv);
}
Gives the following error:
oi.cpp: In function ‘int main(int, char**)’:
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive]
Such a conversion would allow you to put a const char* into your array of char*, which would be unsafe. In print you could do:
thing[0] = "abc";
Now argv[0] would point to a string literal that cannot be modified, while main expects it to be non-const (char*). So for type safety this conversion is not allowed.
#Fred Overflow's link to the FAQ is a complete answer. But (sorry Marshall) it's not the most clear explanation. I don't know if mine is more clear, but I hope so.
The thing is, if p is a char* pointer, then it can be used to modify whatever it's pointing at.
And if you could obtain a pointer pp that points to p, but with pp of type char const**, then you could use pp to assign to p the address of a const char.
And with that, you could then use p to modify the const char. Or, you would think you could. But that const char could even be in read-only memory…
In code:
char const c = 'a';
char* p = 0;
char const** pp = &p; // Not allowed. :-)
*pp = &c; // p now points to c.
*p = 'b'; // Uh oh.
As a practical solution to your code that does not compile, …
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv); // Dang, doesn't compile!
}
just do …
#include <iostream>
void print( char const* const* thing )
{
std::cout << thing[0] << std::endl;
}
int main( int argc, char** argv )
{
print( argv ); // OK. :-)
}
Cheers & hth.,
Note, that although
void dosmth(const char** thing);
int main(int argc, char** argv) {
dosmth(argv);
is forbidden, you can and should do
void dosmth(const char* const* thing);
int main(int argc, char** argv) {
dosmth(argv);
Which is probably what you wanted anyway. The point here is that thing now refers to a const char* array which is itself immutable and which referenced values char are themselves immutable.
So, for a "look at it, but do not change it" scenario, const char* const* is the type to use.
Note: I used the more common (but in my opinion inferior) standard of trying to write the const modifier as left as possible. Personally, I recommend writing char const* const* instead of const char* const* as it is hugely more concise that way.
Because it might allow us to modify a constant value. Read here to understand why: http://c-faq.com/ansi/constmismatch.html

SQLite callback function as class member

I’m trying to make the SQLite callback function part of my class. Any examples? I have tried this but it isn't compiling:
class Customer
{
...
public:
int callback(void* data, int argc, char **argv, char **azColName);
};
std::string Customer::getCustomer()
{
...
int res = sqlite3_exec(db, sqlStatement.c_str(), callback, nullptr, &errMessage);
...
}
The problem is with callback parameter in sqlite3_exec.
You should use static method for sqlite3_exec as a callback.
define:
static int callback(void* data, int argc, char **argv, char **azColName);
call:
int res = sqlite3_exec(db, sqlStatement.c_str(), Customer::callback, nullptr, &errMessage);

c++ read access violation after casting

I have a static method inside my class, which I use for a callback.
Inside this callback I want to add a value to result.
This seems not to be possible because of the recast(?).
Is there a way to access the member variable result and add values to it after recasting, or do I need to think of a different way?
MyClass.h
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
}
MyClass.cpp
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
cout << "working" << endl;
}
main.cpp
int main()
{
MyClass* cl = new MyClass();
cl->Do("something");
}
The documentation states that the fourth argument to sqlite3_exec is passed as the first argument of the callback.
Currently you are passing NULL, which you then cast to a MyClass* and attempt access the object, which results in undefined behaviour.
Use this as the fourth argument in place of NULL.
It seems you are trying to access a non-static member function from a static member callback function c_CB.
You were able to call a member function Callback but nothing from the class is accessible, but if I'm correct, the compiler just interpreted Callback as a static function.
If you actually breakpoint inside this function, you can see that none of your member variables actually have a memory address. And the current class, this is null
I'm not sure if the cout << statement still works or if its causing the problem
This is a possible solution to your issue, although it may not be the best one.
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
void MemberFunction()
{
cout << "working" << endl;
}
static MyClass* currentClass; //Add a static class pointer and assign your class address to it before firing the callback.
}
MyClass* MyClass::currentClass = NULL;
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
currentClass->MemberFunction();
}
int main()
{
MyClass* cl = new MyClass();
MyClass::currentClass = this;
cl->Do("something");
}

const char* to const char**

Is there a easy way to convert a const char* to a const char** in C++ (without the use of Boost)? I've tried to use &myConstCharP but that didn't work.
I can't see a problem here. The following code works fine for me:
int main(int argc, char **argv)
{
char c = 'a';
const char *myConstCharP = &c;
const char **p = &myConstCharP;
printf("Your original char is: %c",**p);
}

C++ Identifier Not Found error

I get identifer not found error for "startProcess":
int main(int argc, char* argv[])
{
bool result=startProcess(argc, argv);
return 0;
}
bool startProcess(int argc, char* argv[])
{
}
But why?
Functions need to be at least declared before you use them, if not defined. Try putting this at the top of your file.
bool startProcess(int argc, char* argv[]);
The above is a declaration, you're telling the compiler that at some point, you're going to provide a definition for the function, which is this:
bool startProcess(int argc, char* argv[])
{
code here...
}
This difference between a declaration and a definition is important for being able to separate your code into separate files. If you had placed your definition of startProcess in a different file, the compiler would never actually see it while compiling the file that contains main. However, with the declaration, you're making a promise that it exists somewhere.
You haven't declared that function before main(), so the compiler is unaware of the existence of startProcess at the point of call:
bool startProcess(int argc, char* argv[]); // <== Informs the compiler about
// the existence of startProcess
// (and about its signature)
int main(int argc, char* argv[])
{
bool result = startProcess(argc, argv); // OK because of the declaration
// above: the compiler knows that
// somewhere (possibly in another
// translation unit) the definition
// of startProcess is provided
return 0;
}
bool startProcess(int argc, char* argv[])
{
// ...
}
Alternatively, you can put the definition directly before main():
bool startProcess(int argc, char* argv[])
{
// ...
}
int main(int argc, char* argv[])
{
bool result = startProcess(argc, argv);
return 0;
}
You should put the declaration of startProcess before main if you would like to put definition of it after main.
bool startProcess(int argc, char* argv[]); //declare here
int main(int argc, char* argv[])
{
bool result=startProcess(argc, argv);
return 0;
}
bool startProcess(int argc, char* argv[])
{
}
or you can put the definition of startProcess directly before main.
Make a prototype before your main function.
bool startProcess(int argc, char* argv[]);