After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 778632 - Unable to pass N-D arrays via signals
Unable to pass N-D arrays via signals
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Code Generator: GSignal
0.35.x
Other Mac OS
: Normal normal
: ---
Assigned To: Vala maintainers
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2017-02-14 21:13 UTC by fcserna
Modified: 2017-03-05 15:39 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch to update marshaller and signal to support N-D array. (3.98 KB, patch)
2017-02-14 21:13 UTC, fcserna
none Details | Review
signalmodule: Add support for array-parameters with rank > 1 (4.64 KB, patch)
2017-03-04 17:54 UTC, Rico Tzschichholz
committed Details | Review

Description fcserna 2017-02-14 21:13:17 UTC
Created attachment 345764 [details] [review]
Patch to update marshaller and signal to support N-D array.

I am unable to pass N-D arrays via signaling.  I have looked at the generated C code and discovered arrays in the marshaller and signal are treated as 1D, ie, a pointer, with 1 int length.

The following code will generate a crash:

public class Test : Object {

    public signal void sig_1(int[,,] a); 
    public int[,,] bla;
    
    public void dump(int[,,] a) {
        stdout.printf("Dump length:[%d,%d,%d]\n",a.length[0],a.length[1],a.length[2]);
        for (var i=0; i< a.length[0]; i++) {
            for (var j=0; j< a.length[1]; j++){
                for (var k=0; k< a.length[2]; k++){
                    stdout.printf("%d\n", a[i,j,k]);
                }   
            }   
        }   
    }   
    
    public void emit() {
        sig_1(bla);
    }   
    
    public Test(int a) {
        bla = new int[2,2,2];
        
        for (var i=0; i<2; i++) {
            for (var j=0; j<2; j++) {
                for (var k=0; k<2; k++) {
                    bla[i,j,k] = j;
                }   
            }   
        }   
        stdout.printf("Constructor length:[%d,%d,%d]\n",bla.length[0],bla.length[1],bla.length[2]);
    }   
}

public static int main(string[] args) {
        Test t1 = new Test(5);
        Test t2 = new Test(0);
        
        t1.sig_1.connect(t2.dump);

        t1.emit();

        return 0;
}

I've attached a patch that updates the array logic in the signal and marshaller to add an int for each array dimension (rank).
Comment 1 Yannick Inizan 2017-02-15 04:02:24 UTC
1) `t1.sig_1.connect(t2.dump);` : you cannot do this because t2 is null when callback is called.

2) 'bla' array is public, you can remove this parameter in signal and write this : `t1.sig_1.connect (() => { t2.dump (t1.bla); });`
Comment 2 fcserna 2017-02-15 19:01:09 UTC
Thanks for the reply.

1) Yes, t2 is null because the closure and marshaller prototypes are wrong.  In c and gdb: 

typedef void (*GMarshalFunc_VOID__POINTER_INT) (gpointer data1, gpointer arg_1, gint arg_2, gpointer data2);
g_return_if_fail (n_param_values == 3);
callback (data1, g_value_get_pointer (param_values + 1), g_value_get_int (param_values + 2), data2);

_test_dump_test_sig_1 (_sender=0x610800, a=0x60ee60, a_length1=2, a_length2=6359104, a_length3=-7888, self=0x0) at vala_simple_signal.c:404

Because we are not passing the other rank lengths of the array (only the first), then the other parameters of the callback function are junk and t2 is null.

My patch makes the following changes to the above:

typedef void (*GMarshalFunc_VOID__POINTER_INT_INT_INT) (gpointer data1, gpointer arg_1, gint arg_2, gint arg_3, gint arg_4, gpointer data2);
g_return_if_fail (n_param_values == 5);
callback (data1, g_value_get_pointer (param_values + 1), g_value_get_int (param_values + 2), g_value_get_int (param_values + 3), g_value_get_int (param_values + 4), data2);

_test_dump_test_sig_1 (_sender=0x60f800, a=0x60f310, a_length1=2, a_length2=2, a_length3=2, self=0x60f840) at vala_simple_signal.c:409

2)  This is a great workaround, and I can make effective use of it in my vala only applications; however, I also bind the use of vala in other languages via gobject introspection, and those other languages do not have anonymous methods. We use signaling to 'push' data to the receiving block, which may or may not be in vala.  I'll think about the design more to see if I can use the anonymous method workaround, but for now, the patch allows us to push data around effectively.
Comment 3 Rico Tzschichholz 2017-03-04 17:54:06 UTC
Created attachment 347224 [details] [review]
signalmodule: Add support for array-parameters with rank > 1
Comment 4 Rico Tzschichholz 2017-03-05 15:39:14 UTC
Attachment 347224 [details] pushed as 972d568 - signalmodule: Add support for array-parameters with rank > 1