when i read the source code of fileIO::read().I came across a problem.
First of all,the fileIO::Read() source code is:
enter int32_t FileIO::Read(int64_t offset,
char* buffer,
int32_t bytes_to_read,
const CompletionCallback& cc)
{
if (has_interface<PPB_FileIO_1_1>()) {
return get_interface<PPB_FileIO_1_1>()->Read(pp_resource(),
offset, buffer, bytes_to_read, cc.pp_completion_callback());
} else if (has_interface<PPB_FileIO_1_0>()) {
return get_interface<PPB_FileIO_1_0>()->Read(pp_resource(),
offset, buffer, bytes_to_read, cc.pp_completion_callback());
}
return cc.MayForce(PP_ERROR_NOINTERFACE);
}
we can see that across get_interface(),we get a Func Pointer.the problem is, how to get this pointer.
then i find the source code of get_interface:
template <typename T> inline T const* get_interface() {
static T const* funcs = reinterpret_cast<T const*>(
pp::Module::Get()->GetBrowserInterface(interface_name<T>()));
return funcs;
}
and then the source code of GetBrowserInterface(),
const void* Module::GetBrowserInterface(const char* interface_name) {
return get_browser_interface_(interface_name);
}
Module::Module() : pp_module_(0), get_browser_interface_(NULL), core_(NULL){}
we can see that when construct the Module,we set the get_browser_interface_ to NULL,and i find nowhere that InternalInit() Func wasn't called at all.
so it Confuses that how to get the Read() Pointer.And where are the source code of the implemention of Read()? thank you.
pp::Module::InternalInit is called in ppp_entrypoints.cc. The functions in this file are called as the entrypoint to the PPAPI Native Client module when you link in the ppapi_cpp library.
Specifically, PPP_InitializeModule is called by the module loader to initialize the Native Client module.
The source code of PPB_FileIO_1_1::Read can be found in the ppapi library here. This forwards to the proxy here.
Related
I have began learning C++ for Arduino and have run into some troubles.
I have some functions reading/writing to SPIFFS files.
Since the code for opening configuration files is common I would want to have a separate function to handle it.
I have come up with following function declaration
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file);
The function accepts pointer to char array for the file path, and pointer to opened file.
I then tried to make following function definition
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file)
{
if (SPIFFS.exists(path))
{
file = &SPIFFS.open(path, "r+");
return !file ? Failed : Opened;
}
else
{
file = &SPIFFS.open(path, "w+");
return !file ? Failed : Created;
}
}
That did not work as compiler complained with error error: taking address of temporary [-fpermissive]
As I understand this means that the file object will be disposed once DeviceOpenConfigFile function returns?
So my question is whether its possible to implement a function in a way where I can get File object reference and release it later?
SPIFFS.open apparently returns File, by value. The returned value will be a temporary variable available on that line. So taking the address of that one doesn't make any sense, for the same reason as int func (void); ... &func() doesn't make any sense. It has nothing to do with the surrounding DeviceOpenConfigFile function.
It doesn't make sense to assign a new address to pointer passed by parameter, for the same reason as void func (int x) { x = 0; } doesn't make sense - you change a local variable only, nothing on the caller side gets changed and nothing gets returned to the caller.
It would seem that the solution you are looking for is this:
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File* file)
{
...
*file = SPIFFS.open(path, "r+");
where file is allocated on the caller-side.
I am writing a function:
void callFunctionAt(uint32_t address){
//There is a void at address, how do I run it?
}
This is in Atmel Studio's C++. If previous questions are to be believed, the simple answer is to write the line "address();". This cannot be correct. Without changing the header of this function, how would one call the function located at the address given?
The answer should be system-agnostic for all micro controllers which support standard c++ compilation.
The common way to do this is to give the argument the correct type. Then you can call it right away:
void callFunctionAt(void (*address)()) {
address();
}
However, since you wrote "Without changing the header of this function [...]", you need to cast the unsigned integer to a function pointer:
void callFunctionAt(uint32_t address) {
void (*f)() = reinterpret_cast<void (*f)()>(address);
f();
}
But this is not safe and not portabel because it assumes that the uint32_t can be casted into a function pointer. And this needs not to be true: "[...] system-agnostic for all micro controllers [...]". Function pointers can have other widths than 32 bits. Pointers in general might consist of more than the pure address, for example include a selector for memory spaces, depending on the system's architecture.
If you got the address from a linker script, you might have declared it like this:
extern const uint32_t ext_func;
And like to use it so:
callFunctionAt(ext_func);
But you can change the declaration into:
extern void ext_func();
And call it directly or indirectly:
ext_func();
callFunctionAt(&ext_func);
The definition in the linker can stay as it is, because the linker knows nothing about types.
There is no generic way. It depends on which compiler you are using. In the following I'll assume avr-g++ because it's common and freely available.
Spoiler: On AVR, it's more complicated than on most other machines.
Suppose you actually have a uint32_t address which would be a byte address. Function pointers in avr-g++ are word addresses actually, where a word has 16 bits. Hence, you'll have to divide the byte address by 2 first to get a word address; then cast it to a function pointer and call it:
#include <stdint.h>
typedef void (*func_t)(void);
void callFunctionAt (uint32_t byte_address)
{
func_t func = (func_t) (byte_address >> 1);
func();
}
If you started with a word address, then you can call it without further ado:
void callFunctionAt (uint32_t address)
{
((func_t) word_address)();
}
This will only work for devices with up to 128KiB of flash memory!
The reason is that addresses in avr-g++ are 16 bits long, cf. the layout of void* as per avr-gcc ABI. This means using scalar addresses on devices with flash > 128KiB will not work in general, for example when you issue callFunctionAt (0x30000) on an ATmega2560.
On such devices, the 16-bit address in Z register used by EICALL instruction is extended by the value held in the EIND special function register, and you must not change EIND after entering main. The avr-g++ documentation is clear about that.
The crucial point here is how you are getting the address. First, in order to call and pass it around properly, use a function pointer:
typedef void (*func_t)(void);
void callFunctionAt (func_t address)
{
address();
}
void func (void);
void call_func()
{
func_t addr = func;
callFunctionAt (addr);
}
I am using void argument in the declaration because this is how you'd do it in C.
Or, if you don't like the typedef:
void callFunctionAt (void (*address)(void))
{
address();
}
void func (void);
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
If you want to call a function at a specific word address like, for example 0x0 to "reset"1 the µC, you could
void call_0x0()
{
callFunctionAt ((func_t) 0x0);
}
but whether this works depends on where your vector table is located, or more specifically, how EIND was initialized by the startup code. What will always work is using a symbol and define it with -Wl,--defsym,func=0 when linking with the following code:
extern "C" void func();
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
The big difference compared to using 0x0 directly it that the compiler will wrap symbol func with symbol modifier gs which it will not do when using 0x0 directly:
_Z9call_funcv:
ldi r24,lo8(gs(func))
ldi r25,hi8(gs(func))
jmp _Z14callFunctionAtPFvvE
This is needed if the address is out of the scope of EIJMP to advise the linker to generate a stub.
1 This will not reset the hardware. The best approach to force a reset is by letting the watchdog timer (WDT) issue a reset for you.
Methods
Yet another situation is when you want the address of a non-static method of a class because you also need a this pointer in that case:
class A
{
int a = 1;
public:
int method1 () { return a += 1; }
int method2 () { return a += 2; }
};
void callFunctionAt (A *b, int (A::*f)())
{
A a;
(a.*f)();
(b->*f)();
}
void call_method ()
{
A a;
callFunctionAt (&a, &A::method1);
callFunctionAt (&a, &A::method2);
}
The 2nd argument of callFunctionAt specifies which method (of a given prototype) you want, but you also need an object (or pointer to one) to apply it. avr-g++ will use gs when taking the method's address (provided the following call(s) cannot be inlined), thus it will also work for all AVR devices.
Based on comments I think you are asking about how microcontroller calls function.
Could you compile your program to see assembly files?
I would recommend you to read one of them.
Every function after compiling are translated to instructions that CPU can do (loading to register, adding to register etc.).
So then your void foo(int x) {statements;} compile to simple CPU instructions and whenever you call foo(x) in your program, you are moving to instructions that are related to foo - you are calling a subroutine.
As far as I remeber there is a CALL function in AVR to invoke subroutines and the name of subroutine is the label where executing program jump and invoking next instruction at adress.
I think you can clarify your doubts when you read some AVR assembly tutorials.
It is fun (at least for me) to see what exactly CPU do when it calls function that I wrote, but it required to know what instructions do. You develop in AVR so there is a set of instructions that you can read about in this PDF and compare with your assembly files.
In QT have the following code that starts a thread to send out commands. The thread takes a char * and int as arguments. In the "run" I use the pointer that is given by the constuctor. The code is:
MyThread::MyThread(char * payld, int payld_size)
{
payload_size = payld_size;
payload_p = payld;
}
void MyThread::run()
{
while(...)
{
sendCommand(payload_p, payload_size);
}
}
Unfortunately this doesn´t work and my application crashes when I try to use thread.start(). But when I change it to:
MyThread::MyThread(char * payld, int payld_size)
{
payload_size = payld_size;
payload_p = payld;
for(int i=0; i<payload_size; i++)
{
payload[i] = payld[i];
}
}
void MyThread::run()
{
while(...)
{
sendCommand(payload, payload_size);
}
}
The code does run and only crashes sometimes (looks pretty random to me). Can anybody Explain me why version one doesnt work and version two does? And any ideas on why the second code sometimes crashes? Could it be because the size of payload is not predefined (in the header file I defined it as
char payload[];
When I define it as:
char payload[10];
it seems to work better, but it is annoying to test since the crashes are pretty random.
instead of fiddling with char*, I would switch to QString (since you're using Qt). It takes a bit of learning, but it's almost mandatory to get code working smoothly in this framework. Then declare
QString payload;
and depending on sendCommand implementation, use one of the member functions QString to get the char*, like payload.toLatin1()
I've something like:
struct list{
struct list **next, **prev;
}
Global declaration:
struct list *threads = &((struct list){&threads, &threads});
void* vp_threads; /Error here: previous declaration of 'vp_threads' was here
vp_threads = threads; //Error here: conflicting types for vp_threads
2nd way I tried:
void* vp_threads = threads; //Error: initializer element is not constant
I have to do this because ... (see below!)
void some_func()
{
add_head(vp_threads, ...)
...
}
void add_head(void* x, ...)
{ ... }
(PS: And there's not main() or initialization function, this's core.c file kind of, implementing all the functions which are in .h)
Why this's not working, I'm just trying to make void* to point to my structure. what's wrong with this?
try doing
vp_threads = threads;
in main ( or an initialization function )
you can't put a statement in global scope. your statement vp_threads = threads; would have to live inside a function somewhere
This is a similar question to this SO post, which I have been unable to use to solve my problem. I have included some code here, which will hopefully help someone to bring home the message that the other posting was getting at.
I want to write a CLI/C++ method that can take a void pointer as a parameter and return the managed object (whose type I know) that it points to. I have a managed struct:
public ref struct ManagedStruct { double a; double b;};
The method I am trying to write, which takes a void pointer to the managed struct as a parameter and returns the struct.
ManagedStruct^ VoidPointerToObject(void* data)
{
Object^ result = Marshal::PtrToStructure(IntPtr(data), Object::typeid);
return (ManagedStruct^)result;
}
The method is called here:
int main(array<System::String ^> ^args)
{
// The instance of the managed type is created:
ManagedStruct^ myData = gcnew ManagedStruct();
myData->a = 1; myData->b = 2;
// Suppose there was a void pointer that pointed to this managed struct
void* voidPtr = &myData;
//A method to return the original struct from the void pointer
Object^ result = VoidPointerToObject(voidPtr);
return 0;
}
It crashes in the VoidPointerToObject method on calling PtrToStructure , with the error: The specified structure must be blittable or have layout information
I know this is an odd thing to do, but it is a situation I have encountered a few times, especially when unmanaged code makes a callback to managed code and passes a void* as a parameter.
(original explanation below)
If you need to pass a managed handle as a void* through native code, you should use
void* voidPtr = GCHandle::ToIntPtr(GCHandle::Alloc(o)).ToPointer();
// ...
GCHandle h = GCHandle::FromIntPtr(IntPtr(voidPtr));
Object^ result = h.Target;
h.Free();
(or use the C++/CLI helper class gcroot)
Marshal::PtrToStructure works on value types.
In C++/CLI, that means value class or value struct. You are using ref struct, which is a reference type despite use of the keyword struct.
A related problem:
void* voidPtr = &myData;
doesn't point to the object, it points to the handle.
In order to create a native pointer to data on the managed heap, you need to use pinning. For this reason, conversion between void* and Object^ isn't as useful as first glance suggests.