I've just started making libraries in Arduino. I've made a library named inSerialCmd. I want to call a function named delegate() that is defined in the main program file, stackedcontrol.ino, after the inSerialCmd library is included.
When I try to compile, one error is thrown:
...\Arduino\libraries\inSerialCmd\inSerialCmd.cpp: In member function
'void inSerialCmd::serialListen()':
...\Arduino\libraries\inSerialCmd\inSerialCmd.cpp:32: error:
'delegate' has not been declared
After doing a bit of searching, it seemed that adding the scope resolution operator might do the trick. So I added the "::" before delegate(), now "::delegate()", but the same error is thrown.
Now I'm stumped.
You cannot and should not directly call a function in a program from a library. Keep in mind a key aspect that makes a library into a library:
A library does not depend on the specific application. A library can be fully compiled and packaged into the .a file without the existence of a program.
So there is a one way dependency, a program depends on a library. This at first glance may seem to prevent you from achieving what you want. You can achieve the functionality you are asking about through what is sometimes referred to as a callback. The main program would provide to the library at runtime a pointer to the function to execute.
// in program somwehere
int myDelegate(int a, int b);
// you set this to the library
setDelegate( myDelegate );
You see this in the arduino if you look at how interrupt handlers are installed. This same concept exists in many environments - event listeners, action adapters - all with the same goal of allowing a program to define the specific action that a library cannot know.
The library would store and call the function via the function pointer. Here is a rough sketch of what this looks like:
// in the main program
int someAction(int t1, int t2) {
return 1;
}
/* in library
this is the delegate function pointer
a function that takes two int's and returns an int */
int (*fpAction)(int, int) = 0;
/* in library
this is how an application registers its action */
void setDelegate( int (*fp)(int,int) ) {
fpAction = fp;
}
/* in libary
this is how the library can safely execute the action */
int doAction(int t1, int t2) {
int r;
if( 0 != fpAction ) {
r = (*fpAction)(t1,t2);
}
else {
// some error or default action here
r = 0;
}
return r;
}
/* in program
The main program installs its delegate, likely in setup() */
void setup () {
...
setDelegate(someAction);
...
Related
This post is a duplicate of the Github Issue here.
dart --version
Dart SDK version: 2.15.0-116.0.dev (dev) (Thu Sep 16 09:47:01 2021 -0700) on "linux_x64"
I've been looking up examples for callbacks and I have tried to get callbacks working for me in FFI.
My current situation
I have a function in my library which expects a pointer to a function. The bindings for the same generated by ffigen seem correct to me.
int SetCallback(
CallbackType callback,
) {
return _SetCallback(
callback,
);
}
late final _SetCallbackPtr =
_lookup<NativeFunction<Int32 Function(CallbackType)>>(
'SetCallback');
late final _SetCallback =
_SetCallbackPtr.asFunction<int Function(CallbackType)>();
where, typedef CallbackType = Pointer<NativeFunction<Void Function(Uint32)>>;.
What I want to do here is to setup this callback in Dart, pass it to the FFI, essentially using it as my callback as I would have in C. In my API which abstracts away from FFI code (which means I have a class MyLibrary full of static functions that the user will call directly, which in turn calls functions from an object _nativeLibrary of the class MyNativeLibrary I have created), I have:
static int SetCallback({required CallbackFuncDart callback}) {
Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback);
int status = _nativeLibrary.SetCallback(
pointer,
);
if (STATUS_OK != status) {
throw LibLexemeException(status);
}
return status;
}
typedef CallbackFunc = Void Function(Uint32);
typedef CallbackFuncDart = void Function(int);
While the sqlite ffi example states here that
Features which dart:ffi does not support yet:
Callbacks from C back into Dart.
I believe the docs haven't been updated to reflect the changes at the samples here. The samples haven't been very clear due to them not having any C/C++ files, or an idea of how the C functions work. Even so, I think this example contains a segment(last code block) where a Dart function is being passed as a callback which I have replicated in my program. It is not clear to me how this will work but upon trying to compile my program I get:
ERROR: ../lib/library_lexeme.dart:180:74: Error: fromFunction expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code. Closures and tear-offs are not supported because they can capture context.
ERROR: Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback);
The short version is that you can't pass your callnback as an argument:
static int SetCallback({required CallbackFuncDart callback}) {
Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback); // <-- this isn't considered a static function
It's quite annoying but you must use a static function defined ahead of time for your dart callbacks to be called from C.
Apparently for now only static functions can be passed via ffi. But if you have to access an instance's data and you're sure that the instance exists you can use my workaround. I use a static list to the instances. This is stupid and ugly but it works for me:
class CallbackClass {
static Int8 classCallback(int id) {
final instance = instanceList[id];
return instance.instanceCallback();
}
Int8 instanceCallback() { return instanceId; }
static List<CallbackClass> instanceList = <CallbackClass>[];
late final int instanceId;
CallbackClass {
instanceId = instanceList.length;
instanceList.insert(instanceId, this);
myFFImapping.passCallback(instanceId, Pointer.fromFunction<>(classCallback);)
}
}
I omitted the necessary c code, FFI mapping and casting to correct types for clarity, so it obviously won't compile like this.
I have a class in c++ that I'm wrapping into python with pybind11. That class has a std::function, and I'd like to control how the arguments to that function are dealt with (like return value policies). I just can't find the syntax or examples to do this...
class N {
public:
using CallbackType = std::function<void(const OtherClass*)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
OtherClass * o = new OtherClass();
callback(o);
}
}
wrapped with
py::class_<OtherClass>(...standard stuff...);
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(),
py::arg("callback"));
I all works: I can do this in python:
def callback(o):
dosomethingwith(o)
k = N(callback)
, but I'd like to be able to control what happens when callback(o); is called - whether python then will take ownership of the wrapped o variable or not, basically.
I put a printout in the destructor of OtherClass, and as far as I can tell, it never gets called.
OK, I think I figured it out:
Instead of std::function, use a pybind11::function:
using CallbackType = pybind11::function
and then
void doit(const OtherClass &input) {
if (<I want to copy it>) {
callback(pybind11::cast(input, pybind11::return_value_policy::copy));
} else {
callback(pybind11::cast(input, pybind11::return_value_policy::reference));
}
}
I see nothing in pybind11/functional that allows you to change the ownership of the parameters at the point of call, as the struct func_wrapper used is function local, so can not be specialized. You could provide another wrapper yourself, but in the code you can't know whether the callback is a Python function or a bound C++ function (well, technically you can if that bound C++ function is bound by pybind11, but you can't know in general). If the function is C++, then changing Python ownership in the wrapper would be the wrong thing to do, as the temporary proxy may destroy the object even as its payload is stored by the C++ callback.
Do you have control over the implementation of class N? The reason is that by using std::shared_ptr all your ownership problems will automagically evaporate, regardless of whether the callback function is C++ or Python and whether it stores the argument or not. Would work like so, expanding on your example above:
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
namespace py = pybind11;
class OtherClass {};
class N {
public:
using CallbackType = std::function<void(const std::shared_ptr<OtherClass>&)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
auto o = std::make_shared<OtherClass>();
callback(o);
}
};
PYBIND11_MODULE(example, m) {
py::class_<OtherClass, std::shared_ptr<OtherClass>>(m, "OtherClass");
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(), py::arg("callback"))
.def("doit", &N::doit);
}
In a C++/CLI assembly, I'm trying to call a managed delegate from a native callback. I followed Doc Brown's answer here, and my implementation so far looks like this:
The native callback - ignore the commented out parts for now:
static ssize_t idaapi idb_callback(void* user_data, int notification_code, va_list va)
{
switch (notification_code)
{
case idb_event::byte_patched:
{
//ea_t address = va_arg(va, ea_t);
//uint32 old_value = va_arg(va, uint32);
return IdaEvents::BytePatched(0, 0);
}
break;
}
return 0;
}
As you can see above, I call this managed delegate instantiated in a static class:
public delegate int DatabaseBytePatchedHandler(int address, int originalValue);
private ref class IdaEvents
{
static IdaEvents()
{
BytePatched = gcnew DatabaseBytePatchedHandler(&OnDatabaseBytePatched);
}
public: static DatabaseBytePatchedHandler^ BytePatched;
private: static int OnDatabaseBytePatched(int address, int originalValue)
{
return 0;
}
};
This compiles fine. But the code is incomplete - remember the commented out part in the native callback above? I actually have to retrieve the values from the va_list passed to the callback, and pass those on to my managed delegate:
ea_t address = va_arg(va, ea_t);
uint32 old_value = va_arg(va, uint32);
return IdaEvents::BytePatched(address, old_value);
But as soon as I uncomment one of the lines using va_arg, I cannot compile the project anymore and retrieve the following errors marking the line where I call the managed delegate:
C3821 'IdaEvents': managed type or function cannot be used in an unmanaged function
C3821 'IdaEvents::BytePatched': managed type or function cannot be used in an unmanaged function
C3821 'BytePatched': managed type or function cannot be used in an unmanaged function
C3821 'DatabaseBytePatchedHandler::Invoke': managed type or function cannot be used in an unmanaged function
C3642 'int DatabaseBytePatchedHandler::Invoke(int,int)': cannot call a function with __clrcall calling convention from native code
C3175 'DatabaseBytePatchedHandler::Invoke': cannot call a method of a managed type from unmanaged function 'idb_callback'
This really confuses me. Why is the compiler suddenly acting up as soon as I try to use va_arg? Even a single line without any assignment causes this error to pop up.
Am I thinking too naive here? I'm obviously missing a piece of the puzzle, and any help supporting me in finding it is greatly appreciated.
I want to run some code before main begins, and before constructors for static variables run. I can do with with code like this (ideone)
extern "C" {
static void do_my_pre_init(void) {
// something
}
__attribute__ ((section (".preinit_array"))) void(*p_init)(void) = &do_my_pre_init;
}
Are there any language features that will not work correctly when executed in this function, due to _init and .init_array not yet having been executed?
Or is it only user code that should be hooking into this mechanism?
Some background on __libc_init_array
The source for a typical __libc_init_array is something like:
static void __libc_init_array() {
size_t count, i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i]();
_init();
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i]();
}
Where the __... symbols come from a linker script containing
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
Are there any language features that will not work correctly when executed in this function, due to _init and .init_array not yet having been executed?
This question is impossible to answer in general, because the language itself has no concept of .preinit_array, or _init, or .init_array. All of these concepts are implementation details for a particular system.
In reality, you aren't guaranteed to have anything work at all. Things as simple as malloc may not work (e.g. because the malloc subsystem itself may be using .preinit_array to initialize itself).
In practice, using dynamic linking on a GLIBC-based platform most everything will work (because libc.so.6 initializes itself long before the first instruction of the main executable runs).
For fully-static executable, all bets are off.
For non-GLIBC platform, you'll need to look into specifics of that platform (and you are very unlikely to find any guarantees).
Update:
Can I make function calls,
Function calls need no setup with fully-static linking, and need dynamic loader to have initialized in dynamic linking case. No dynamic loader will start executing code in the application before it has fully initialized itself, so function calls should be safe.
assign structs
In C, at best, this is a few instructions. At worst, this is a call to memcpy or memset. That should be safe.
use array initializers.
This is just a special case of struct assignment, so should be safe.
I'm trying to use class objects with the Arduino, but I keep running into problems. All I want to do is declare a class and create an object of that class. What would an example be?
On Arduino 1.0, this compiles just fine:
class A
{
public:
int x;
virtual void f() { x=1; }
};
class B : public A
{
public:
int y;
virtual void f() { x=2; }
};
A *a;
B *b;
const int TEST_PIN = 10;
void setup()
{
a=new A();
b=new B();
pinMode(TEST_PIN,OUTPUT);
}
void loop()
{
a->f();
b->f();
digitalWrite(TEST_PIN,(a->x == b->x) ? HIGH : LOW);
}
There is an excellent tutorial on how to create a library for the Arduino platform. A library is basically a class, so it should show you how its all done.
On Arduino you can use classes, but there are a few restrictions:
No new and delete keywords
No exceptions
No libstdc++, hence no standard functions, templates or classes
You also need to make new files for your classes, you can't just declare them in your main sketch. You also will need to close the Arduino IDE when recompiling a library. That is why I use Eclipse as my Arduino IDE.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230935955 states:
By default, the Arduino IDE and
libraries does not use the operator
new and operator delete. It does
support malloc() and free(). So the
solution is to implement new and
delete operators for yourself, to use
these functions.
Code:
#include <stdlib.h> // for malloc and free
void* operator new(size_t size) { return malloc(size); }
void operator delete(void* ptr) { free(ptr); }
This let's you create objects, e.g.
C* c; // declare variable
c = new C(); // create instance of class C
c->M(); // call method M
delete(c); // free memory
Regards,
tamberg
I created this simple one a while back. The main challenge I had was to create a good build environment - a makefile that would compile and link/deploy everything without having to use the GUI. For the code, here is the header:
class AMLed
{
private:
uint8_t _ledPin;
long _turnOffTime;
public:
AMLed(uint8_t pin);
void setOn();
void setOff();
// Turn the led on for a given amount of time (relies
// on a call to check() in the main loop()).
void setOnForTime(int millis);
void check();
};
And here is the main source
AMLed::AMLed(uint8_t ledPin) : _ledPin(ledPin), _turnOffTime(0)
{
pinMode(_ledPin, OUTPUT);
}
void AMLed::setOn()
{
digitalWrite(_ledPin, HIGH);
}
void AMLed::setOff()
{
digitalWrite(_ledPin, LOW);
}
void AMLed::setOnForTime(int p_millis)
{
_turnOffTime = millis() + p_millis;
setOn();
}
void AMLed::check()
{
if (_turnOffTime != 0 && (millis() > _turnOffTime))
{
_turnOffTime = 0;
setOff();
}
}
It's more prettily formatted here: http://amkimian.blogspot.com/2009/07/trivial-led-class.html
To use, I simply do something like this in the .pde file:
#include "AM_Led.h"
#define TIME_LED 12 // The port for the LED
AMLed test(TIME_LED);
My Webduino library is all based on a C++ class that implements a web server on top of the Arduino Ethernet shield. I defined the whole class in a .h file that any Arduino code can #include. Feel free to look at the code to see how I do it... I ended up just defining it all inline because there's no real reason to separately compile objects with the Arduino IDE.
Can you provide an example of what did not work? As you likely know, the Wiring language is based on C/C++, however, not all of C++ is supported.
Whether you are allowed to create classes in the Wiring IDE, I'm not sure (my first Arduino is in the mail right now). I do know that if you wrote a C++ class, compiled it using AVR-GCC, then loaded it on your Arduino using AVRDUDE, it would work.