Refer to this small top-of-my-head coed snippet:
typedef void __fastcall (__closure *GetHTTPCallBack)(String filename);
class Foo {
private:
public:
GetHTTPCallBack Callback;
__fastcall Foo (void) { Callback = NULL; }
__fastcall Foo (GetHTTPCallBack callback) { Callback = callback; }
};
class Bar {
private:
Foo *foo;
public:
void __fastcall CallbackFunction(String fileName) { // Do something }
void __fastcall SetByConstructor(void) { foo = new Foo(CallbackFunction); }
void __fastcall SetByAssignment (void) { foo = new Foo(); foo->Callback = CallbackFunction; }
};
Bar bar;
Now to the problem.
If Call bar.SetByAssignment() it works fine, the function pointer is set and called correctly from Foo. But in this case it is exposed as a public variable. I would like it to be private.
I would like to simplify the class, and hide it to be private, by passing the function pointer in the constructor, bar.SetByConstructor() but here I get compiler error:
[bcc32 Error] : Member function must be called or its address taken
I thought the __closure would make this possible. Is it possible at all or I'm I just doing it wrong?
Do what the compiler tells you. Pass the memory address of the method. How do you get the memory address of anything? Use the & address operator:
foo = new Foo(&CallbackFunction);
It is good habit to do that when using an assignment as well (though in that case it is optional):
foo->Callback = &CallbackFunction;
Related
I am developing nema stepper motor driver interfacing with arduino. I created a class. I named it Axis. I want to create an axis object for each motor with this class. but, I can not call the attachInterrupt function in the arduino.h from the class. It return this error :
In member function 'void Axis::setReverseInt()':
parsstep.cpp:12:77: error: invalid use of non-static member function 'void Axis::revDirection()'
attachInterrupt(digitalPinToInterrupt(reverseDirPin), revDirection, RISING);
Axis::Axis()
{
}
Axis::~Axis()
{
}
void Axis::setReverseInt () {
attachInterrupt(digitalPinToInterrupt(reverseDirPin), revDirection, RISING);
}
void Axis::setStopInt () {
//attachInterrupt(digitalPinToInterrupt(stopPin), stopMotor, RISING);
}
void Axis::revDirection()
{
dirMode = !dirMode;
}
void Axis::stopMotor()
{
moveMotor = !moveMotor;
}
void Axis::startMotor()
{
moveMotor = true;
}
void Axis::moveStep(int pulseRev, byte laps, boolean dir)
{
digitalWrite(dirPin, dir);
int totalPulse = pulseRev * laps;
for (int i = 0; i < totalPulse; i++)
{
speedValue = map((analogRead(speedPin)), 0, 1023, 2000, 10);
digitalWrite(pulsePin, HIGH);
delayMicroseconds(speedValue);
digitalWrite(pulsePin, LOW);
delayMicroseconds(speedValue);
}
}
I faced a similar issue when writing my own libraries for a big project I've been working on. It happened to me while configuring interrupts inside a method. I found a workaround that while it might seem a bit more complex, it does the trick. In my case, I used it for reading a rotary encoder its switch.
What I used is a pointer to an ISR handler and a method to call it. On your setup function you can call the initialization of the ISR service.
First, in your .h file declare the following methods (in addition to your own):
void init();
static void ISRHandler();
void setupISRHandler(uint8_t pin, void (*ISR)(void), int state); // this will configure your ISR
and a pointer:
static Axis *_ISRPointer; // can be declared as private (like in here from the '_' prefix)
Then, in your .cpp file you use it like this:
#include "Axis.h"
Axis *Axis::_ISRPointer = nullptr;
you will initialize the ISR handler during the setup using the init method:
void Axis::init(){
setupISRHandler(reverseDirPin, Axis::ISRHandler, RISING);
}
the setup method looks like:
void Axis::setupISRHandler(uint8_t pin, void (*ISRFunction)(void), int state){
attachInterrupt(digitalPinToInterrupt(pin), ISRFunction, state);
}
the ISRHandler is in charge of calling the ISR routine:
void Axis::ISRHandler(){
_ISRPointer-> revDirection();
}
void Axis::revDirection(void){
// Do not forget to disable interrupts
cli();
// your routine goes here
dirMode= !dirMode;
sei();
}
Therefore, you will do something like this in your main .ino file:
#include "Axis.h"
#include <whateverotherlibraryyouneed.h>
Axis ax = Axis(); // your new object
void setup(){
ax.init();
ax.startMotor();
}
void loop(){
if(day == SUNNY){
ax.moveStep(100, 2 , CLOCKWISE);
} else {
ax.stopMotor();
}
ax.someOtherMethodToControlTheMotor(anyArgumentYouWant);
}
I hope that my convoluted solution helps
Cheers
Dr. Daniel
I am new to Dart and Flutter, I wanted to know what i the actual difference and when to use which one.
A function is a top-level function which is declared outside of a class or an inline function that is created inside another function or inside method.
A method is tied to an instance of a class and has an implicit reference to this.
main.dart
// function
void foo() => print('foo');
// function
String bar() {
return 'bar';
}
void fooBar() {
int add(int a, int b) => a + b; // inline function
int value = 0;
for(var i = 0; i < 9; i++) {
value = add(value, i); // call of inline function
print(value);
}
}
class SomeClass {
static void foo() => print('foo'); // function in class context sometimes called static method but actually not a method
SomeClass(this.firstName);
String firstName;
// a real method with implicit access to `this`
void bar() {
print('${this.firstName} bar');
print('$firstName bar'); // this can and should be omitted in Dart
void doSomething() => print('doSomething'); // inline function declared in a method
doSomething(); // call of inline function
}
}
Like inline functions you can also create unnamed inline functions, also called closures. They are often used as callbacks like
button.onClick.listen( /* function start */ (event) {
print(event.name);
handleClick();
} /* function end */);
Shouldn't this (or something like it) work? and/or How can I accomplish this some other way?
class A {
void init() {initializeSomething()}
}
main() {
var f = A.init;
A a = new A();
a.f();
}
I want, in general, to store a reference to an instance method
somewhere, then call it somewhere else (something I can do in most other
languages, including JavaScript). I thought functions were first class
in Dart... and aren't methods functions? Are methods not first class?
It works as long as the method is static (which is of no use in my case) but not for instance methods...
Functions and methdods are different. You can only call methods on an instance of a class that has this method.
In your example (var f = A.init) you reference an instance method like a static (class) method.
What works is:
make init static
class A {
static void init() => initializeSomething();
// or
// static void init() {
// initializeSomething();
// }
}
main() {
var f = A.init;
A a = new A();
a.f();
}
or use a reference to init() of an actual instance of A:
class A {
void init() => initializeSomething();
}
main() {
A a = new A();
var f = a.init;
a.f();
}
Is it possible to have two or more outer function-scoped functions that have mutual call dependencies on each other?
I'm asking because
void main(string args[]) {
int x = 42;
void a() {
// do something with x
b();
}
void b() {
// do something with x
a();
}
}
errors in DMD as
/home/per/Work/justd/t_funs.d(5): Error: undefined identifier b
If not is this an unresolved issue or a feature?
you can declare the delegate b before a and then assign b
void main(string args[]) {
int x = 42;
void delegate() b;
void a() {
// do something with x
b();
}
b = delegate void () {
// do something with x
a();
};
}
it'll require a refactor but not as bad as throwing it all in structs
Let's say you could. Then you could do:
void main(string args[]) {
void a() {
b();
}
a();
int x = 42;
void b() {
// do something with x
a();
}
}
And viola - you use x before declaring it.
There are workarounds to that - like ratchet freak said you could use a delegate, but you could also use a struct:
void main(){
int x=5;
struct S{
void a(){
writefln("in a, x=%d",x);
--x;
if(0<x){
b();
}
}
void b(){
writefln("in b, x=%d",x);
--x;
if(0<x){
a();
}
}
}
S().a();
}
Notice that both solutions prevent using x before it's declaration. If you use a delegate you can't call it before you assign a function to it, which you can only do after you declare the other function, which happens after you declare x. If you use a struct you can't declare x either before of in the struct - but you can only call the functions after the struct is declared - which also means after x is declared.
That's by design: "Unlike module level declarations, declarations within function scope are processed in order." (http://dlang.org/function.html#variadicnested)
Don't know the rationale though.
I need to run code in a class declaration before its instanciation. This would be especially useful to automatically register classes in a factory. See:
// Main.as
public class Main extends Sprite
{
public function Main() : void
{
var o : Object = Factory.make(42);
}
}
// Factory.as
public class Factory
{
private static var _factory : Array = new Array();
public static function registerClass(id : uint, c : Class) : void
{
_factory[id] = function () : Object { return new c(); };
}
public static function make(id : uint) : Object
{
return _factory[id]();
}
}
// Foo.as
public class Foo
{
// Run this code before instanciating Foo!
Factory.registerClass(CLASS_ID, Foo);
public static const CLASS_ID : uint = 42;
}
AFAIK, the JIT machine for the ActionScript language won't let me do that since no reference to Foo is made in the Main method. The Foo class being generated, I can't (and don't want to) register the classes in Main: I'd like to register all the exported classes in a specific package (or library). Ideally, this would be done through package introspection, which doesn't exist in ActionScript 3.
Do you know any fix (or other solution) to my design issue?
I'm not 100% sure sure if this is what you're after, but have you tried using a Static Initializer?
public class Foo
{
// Static Initializer
{
Factory.registerClass(CLASS_ID, Foo);
}
public static const CLASS_ID : uint = 42;
}
http://life.neophi.com/danielr/2006/12/static_initializers_in_as3.html
You can use compiler options to include class byte code in the resulting SWF or SWC. But you have to compile with MXMLC (or COMPC for SWCs).