first, some definitions from /usr/share/vala/vapi/libarchive.vapi
[CCode (cprefix="ARCHIVE_", lower_case_cprefix="archive_", cheader_filename = "archive.h")]
namespace Archive {...
[CCode (instance_pos = 1.9, cname="archive_open_callback")]
public delegate int OpenCallback (Archive archive);
...
[CCode (cname = "struct archive", free_function="archive_write_finish")]
public class Write : Archive {...
public Result open (
[CCode (delegate_target_pos = 0.9)] OpenCallback ocb,
[CCode (delegate_target_pos = 0.9)] WriteCallback rcb,
[CCode (delegate_target_pos = 0.9)] CloseCallback ccb
);
}
}
then my code
int mOpenCallback (Write archive)
{
return Result.OK;
}
void foo(){...
Write archive = new Write();
archive.open(mOpenCallback,mWriteCallback,mCloseCallback);
...}
results : error: Assignment: Cannot convert from mOpenCallback' toArchive.OpenCallback'
what's wrong with it ?
then I tried this instead
namespace Archive {
int OpenCallback (Write archive)
{
return Result.OK;
}
}
void foo(){...
Write archive = new Write();
archive.open(OpenCallback,mWriteCallback,mCloseCallback);
...}
but it outputs : Archive' already contains a definition forOpenCallback'
void foo(){...
Write archive = new Write();
Archive.OpenCallback t = mOpenCallback;
archive.open(t,mWriteCallback,mCloseCallback);
...}
outputs error: Assignment: Cannot convert from foo.mOpenCallback' toArchive.OpenCallback'
mOpenCallback has takes an argument of type Write, not Archive, so it has a different type from the delegate OpenCallback. If you expect Write, you should perform the cast from Archive to write inside your call back.
Related
I'm trying to understand Vala delegates with Gtk3.
I tested callback and lambda with no problem.
I wanna test a delegate callback, here my code :
using Gtk;
delegate void typeDelegate(Button button);
int main (string[] args) {
Gtk.init (ref args);
typeDelegate cb = cbLabelf;
var window = new Window ();
window.title = "First GTK+ Program";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
var button = new Button.with_label ("Click me!");
//button.clicked.connect (cb);
//button.clicked+= cb;
button.clicked.connect+=cb;
window.add (button);
window.show_all ();
Gtk.main ();
return 0;
}
void cbLabelf(Button button)
{
button.label = "tank yu";
}
I also red generated C code ( when i use lambda) to understand.
Here the compil error :
GTKsampleDelegate.vala:20.5-20.30: error: Arithmetic operation not supported for types Gtk.Button.clicked.connect' andtypeDelegate'
button.clicked.connect+=cb;
Well,
Seems that you want to get the intrinsic variable that holds the instance that emitted the signal, I find strange that vala doesn't let you use a delegate variable to obtain it via parameter, yet, you can use one of the forms below: using no delegation variable (A) or bypassing the error with a closure (B).
public class FooSignalClass : Object {
/* Gtk Button.clicked signal has the void f(void) signature */
public signal void on_foo ();
public void foo() {
on_foo();
}
}
public delegate void FooSignalFunc (FooSignalClass fooer);
void on_foo_handler (FooSignalClass fooer) {
long fooer_memory_address = (long)fooer;
GLib.message(#"fooer exists? $(fooer!=null).");
GLib.message(#"address=$fooer_memory_address.");
}
int main () {
var foo_signal = new FooSignalClass();
long fooer_memory_address = (long)foo_signal;
GLib.message(#"foo_signal address=$fooer_memory_address.");
/* Option A: Connect directly without the delegate variable */
foo_signal.on_foo.connect(on_foo_handler);
/* Option B: You cant use a delegate directly, bypass it with a closure */
FooSignalFunc func = on_foo_handler;
foo_signal.on_foo.connect((instance) => {
func(instance);
});
foo_signal.foo();
return 0;
}
Is it possible to initialize abstract base class' protected member for all derived objects without writing the same initializer list in all derived class constructors? So that it acts like a static member for all derived objects. What I want is something like this (except it doesn't work) Read it like a pseudo code:
A.h
class A {
public:
A(string fn);
virtual ~A();
virtual void open_file() = 0;
protected:
string fileName;
};
A.cpp
A::A(string fn) : fileName {fn} {} //Initializer list is written only once here
A::~A() {}
B.h
class B : public A {
public:
B();
~B();
void open_file() const override;
};
B.cpp
B::B() {} //No initializer list for A::fileName here
void B::open_file() const {
ifstream SomeFile(fileName); //Use base class' protected member
..... //Do some stuff with open file
}
And imagine there's also a C derived class without an initializer list for A here that has a different overriden open_file function..
main.cpp
string fname = {"foo.txt"};
A* APtr = new B(fname); //This initializes A's fileName for all derived objects as "foo.txt"
Aptr->open_file(); //B opens foo.txt
fname = "bar.txt";
A* A2Ptr = new C(fname); //Now fileName that both B and C consume is changed to "bar.txt"
A2Ptr->open_file(); //C opens bar.txt
APtr->open_file(); //B now opens bar.txt
You deklared the constructor from B: B(); but you try to use it A* APtr = new B(fname); So the compiler can't find any matching constructor.
initialize abstract base class' protected member for all derived objects without writing the same initializer list in all derived class
Why not?
A.hpp
class A
{
public:
A( string fn = "") : fileName(fn){} // you can give an default path if prefered.
};
B.hpp
class B : public A
{
public:
B( string fn = "") : A( fn ) {} //c++11 feature: call base constructor.
}
Other possible solutions were:
global variable (dirty and unsafe! - Please don't do it.)
static variable in A. But you can only open one file the same time.
give A setter and getter for fileName. And use it that way:
main.cpp
B* b = new B();
b->setFileName("foo.txt");
b->openFile();
I am writting a little ruby module with some very simple classes in C:
typedef struct window_t {
GtkWidget * widget;
}
static void c_window_struct_free(window_t *c)
{
if(c)
{
ruby_xfree(c);
}
}
static VALUE c_window_struct_alloc( VALUE klass)
{
return Data_Wrap_Struct(klass, NULL, c_window_struct_free,ruby_xmalloc(sizeof(window_t)));
}
VALUE c_window = rb_define_class_under(m_rtortosa, "Window", c_widget)
rb_define_method(c_window, "set_title",RUBY_METHOD_FUNC(window_set_title), 1);
//For each class I don't rewritte any "new" or "initialize" function. I let the default
When my module is initialized, a gtk window is created, and I have a ruby method for this module that call:
static VALUE rtortosa_window(VALUE self)
{
VALUE win;
VALUE m_rtortosa = rb_const_get( rb_cObject, rb_intern( "Rtortosa" ) );
VALUE cWindow = rb_const_get_at( m_rtortosa, rb_intern("Window") );
win = rb_class_new_instance(0, NULL, backbone.rb_objects.cWindow);
window_t *w;
Data_Get_Struct(win,window_t, w);
w->widget = backbone.window.widget;
return win;
}
The problesm occurs when I call the rtortosta_window from ruby, it throws an error like this :
wrong argument type Rtortosa::Window (expected Data) (TypeError)
After investigations this message is comming from the Data_Get_Struct function.
I don't see what I am doing wrong, I have a notebook class that is written in the same way but it works as expected.
I have forgotten to bind the alloc function to the class:
rb_define_alloc_func(c_window, c_window_struct_alloc);
I'm just trying to convert my code from C# to Haxe NME. I use enums as flags.
[Flags]
enum State
{
StateOne = 1,
StateTwo = 2,
StateThree = 4
}
And use it
if (someObj.HasState(State.StateOne | State.StateTwo))
{
// Contains both the states. Do something now.
}
I had no idea on how to do this in Haxe NME.
Thanks.
In Haxe 3, there is haxe.EnumFlags. This uses Haxe 3 Abstract Types which basically wrap an underlying type, in this case, it uses an Int, just like you have done - but then it wraps it up in a pretty API so you don't have to worry about the details.
Here is some sample code:
import haxe.EnumFlags;
class EnumFlagTest
{
static function main()
{
var flags = new EnumFlags<State>();
flags.set(StateOne);
flags.set(StateTwo);
flags.set(StateThree);
flags.unset(StateTwo);
if (flags.has(StateOne)) trace ("State One active");
if (flags.has(StateTwo)) trace ("State Two active");
if (flags.has(StateThree)) trace ("State Three active");
if (flags.has(StateOne) && flags.has(StateTwo)) trace ("One and Two both active");
if (flags.has(StateOne) && flags.has(StateThree)) trace ("One and Three both active");
}
}
enum State
{
StateOne;
StateTwo;
StateThree;
}
All of this works is stored as a standard Int, and uses integer operators like you have done, so it should be pretty fast (no wrapping in an external object). If you want to see how it works under the box, the source code for EnumFlags can be viewed here.
If you're still on Haxe 2, then you could create an object that is really similar, but of course, it has to create an object as well as the integer, so if you're doing thousands (millions?) of them then you might get a slow down. The equivalent code, that should work with Haxe 2 (though I haven't checked):
class MyEnumFlags<T:EnumValue>
{
var i:Int;
public function new(?i=0)
{
this.i = i;
}
public inline function has( v : T ) : Bool {
return i & (1 << Type.enumIndex(v)) != 0;
}
public inline function set( v : T ) : Void {
i |= 1 << Type.enumIndex(v);
}
public inline function unset( v : T ) : Void {
i &= 0xFFFFFFF - (1 << Type.enumIndex(v));
}
public inline static function ofInt<T:EnumValue>( i : Int ) : MyEnumFlags<T> {
return new MyEnumFlags<T>(i);
}
public inline function toInt() : Int {
return i;
}
}
I've managed to find it. I had trouble using enums but I had been successful using constants. This is the simple test file I used.
package ;
class FlagsTest
{
static inline var FLG_1:Int = 1;
static inline var FLG_2:Int = 2;
public static function main() : Void
{
var flag:Int = FLG_1;
if (hasFlag(flag, FLG_1))
{
trace ("Test 1 passed");
}
flag |= FLG_2;
if (hasFlag(flag, FLG_2))
{
trace ("Test 2 passed");
}
}
public static function hasFlag( flags:Int, flag:Int ) : Bool
{
return ((flags & flag) == flag) ? true : false;
}
}
Output:
FlagsTest.hx line 14: Test 1 passed
FlagsTest.hx line 19: Test 2 passed
I wrote a class method using STL find_if. The code is the following:
void
Simulator::CommunicateEvent (pEvent e)
{
pwEvent we (e);
std::list<pEvent> l;
for (uint32_t i = 0; i < m_simulatorObjects.size (); i++)
{
l = m_simulatorObjects[i]->ProcessEvent (we);
// no action needed if list is empty
if (l.empty ())
continue;
// sorting needed if list comprises 2+ events
if (l.size () != 1)
l.sort (Event::Compare);
std::list<pEvent>::iterator it = m_eventList.begin ();
std::list<pEvent>::iterator jt;
for (std::list<pEvent>::iterator returnedElementIt = l.begin ();
returnedElementIt != l.end ();
returnedElementIt++)
{
// loop through the array until you find an element whose time is just
// greater than the time of the element we want to insert
Simulator::m_eventTime = (*returnedElementIt)->GetTime ();
jt = find_if (it,
m_eventList.end (),
IsJustGreater);
m_eventList.insert (jt, *returnedElementIt);
it = jt;
}
}
}
Unfortunately, I later discovered that the machine that will run the code is equipped with the libstdc++ library version 4.1.1-21, which apparently is lacking find_if. Needless to say, I cannot upgrade the library, nor can I ask someone to do it.
When compiling, the error I get is:
simulator.cc: In member function ‘void sim::Simulator::CommunicateEvent(sim::pEvent)’:
simulator.cc:168: error: no matching function for call to ‘find_if(std::_List_iterator<boost::shared_ptr<sim::Event> >&, std::_List_iterator<boost::shared_ptr<sim::Event> >, sim::Simulator::<anonymous struct>&)’
simulator.cc: In static member function ‘static void sim::Simulator::InsertEvent(sim::pEvent)’:
simulator.cc:191: error: no matching function for call to ‘find_if(std::_List_iterator<boost::shared_ptr<sim::Event> >&, std::_List_iterator<boost::shared_ptr<sim::Event> >, sim::Simulator::<anonymous struct>&)’
make: *** [simulator.o] Error 1
How can I solve the problem?
I thought I could define a find_if function as described here. However, I have some concerns:
What about performance? The function that makes use of find_if needs to be as efficient as possible.
How can I do conditional compilation? I couldn't find a macro telling the version of the libstdc++ installed.
What are your thoughts about it?
TIA,
Jir
References
Source files: simulator.h and simulator.cc
Solution
Defined IsJustGreater outside the Simulator class and declared IsJustGreater_s friend of Simulator:
struct IsJustGreater_s : public std::unary_function<const pEvent, bool> {
inline bool operator() (const pEvent e1) {return (e1->GetTime () > Simulator::m_eventTime);}
} IsJustGreater;
Called IsJustGreater in find_if this way:
jt = find_if (it, m_eventList.end (), sim::IsJustGreater);
From the error, it appears that you're attempting to use an anonymous type as the argument. I do not believe anonymous types are allowed to be template arguments.
From the error, I believe you have something like this:
class Simulator {
struct {
bool operator(const pEvent& p) { ... } ;
} IsJustGreater;
}
what you want is to give it a name and then change the find_if to instantiate the class (see below)
class Simulator {
// class is now an inner named-class
struct IsJustGreater {
bool operator(const pEvent& p) { ... } ;
};
}
// This is how you use the class
jt = std::find_if(it, m_eventList.end(), IsJustGreater() );
I see that you're using the std:: qualifier before std::list but not std::find_if. Try putting the std:: in front so that the compiler can find it within the namespace.