Working with C/C++ structures/unions |
PBInvoke library documetation > Advanced > Working with C/C++ structures/unions |
PBInvoke supports full access to C++ structs/unions from PowerBuilder.
Because there is no equivalents for unions and field types such as pointers to structures and function pointers in PowerBuilder, PBInvoke have a special object for storing such values: n_pi_value.
Working with nested structures and unions.
Suppose you have the following structure declaration:
n_pi_core lnv_core lnv_core.of_declare("struct MYSTR { union { int ival; char* sval;} u; char ch;}") |
This is a structure MYSTR which has a field of type char, 'ch', and a field of type union 'u',
which itself has two fields 'ival' and 'sval', which share the same memory.
Some examples of working with the structure:
n_pi_core lnv_core n_pi_value lnv_str // Create an instance of the structure in memory // In C++: MYSTR str; lnv_str = lnv_core.of_create_value_of("MYSTR"); // Fill the structure's memory with zero bytes. // Note, however, that of_create_value_of() does it anyway. // C++: memset(&str, sizeof(MYSTR), 0); lnv_str.of_set(0) // Assign to sval field of the union // C++: str.u.sval = "test"; lnv_str.of_item("u").of_set("sval", "test") |
A few words regarding what does n_pi_value.of_item do. When you call of_item("fieldname"),
a n_pi_value is returned which is a reference to the field. No data is copied. When you modify this reference,
the original structure is modified.
of_item() is used most often for accessing nested structures. If you have a field of a simple type
(string, numeric) you use of_get("field")/of_set("field", value) instead of of_item("field").
Also note, that field name in of_item(), of_get(), of_set() is case sensitive.
// Read the value of ival which now holds the pointer to the string "test" because ival and sval share their memory. // C++: int i = str.u.ival; ll_i = lnv_str.of_item("u").of_get("ival") // Assign to ch field of the structure // C++: str.ch = 'A'; lnv_str.of_set("ch", "A") lnv_str.of_set(2, "A") // Fields can also be accessed by a 1-based index in order of their declarations. // Pass the structure as a parameter to a function: // C++: void fn1(MYSTR s) { } // fn1(str) n_pi_method lnv_fn1 lnv_fn1 = lnv_somedll.of_declare_method("void fn1(MYSTR s)") lnv_fn1.of_invoke(lnv_str) // lnv_str's value is copied. // Pass the structure as a pointer parameter to a function: // C++: void fn2(MYSTR *s) { s->u.sval = "fn2"; }; // fn2(&str) lnv_fn2 = lnv_somedll.of_declare_method("void fn2(MYSTR *s)") lnv_fn2.of_invoke(lnv_str) // implicitly gets the address of the structure //or lnv_fn2.of_invoke(lnv_str.of_get_addr()) // which is the same, but explicit. // If the structure is modified in fn2 we'll see those changes String ls_mod ls_mod = lnv_str.of_item("u").of_get("sval") // returns "fn2" |
Working with pointers to structures as fields.
Pointers to a type require dereferencing in order to allow access to the value they point to.
lnv_core.of_declare("struct N { int a;}") // declare a struct lnv_core.of_declare("struct S { N* n;}") // declare a struct with nested pointer to a struct // create an instance // C++: S str; lnv_str = lnv_core.of_create_value_of("S") // init the pointer n with the address of an instance of N // C++: s.n = new N(); lnv_str.of_set("n", lnv_core.of_create_value_of("N")) // access the nested field, a // C++: str.n->a = 123; lnv_str.of_item("n").of_deref().of_set("a", 123) // get the nested structure as separate reference // C++: N &n = *str.n; lnv_n = lnv_str.of_item("n").of_deref() // note this is just a reference, not a copy. //Now lnv_n.of_get("a") is the same as lnv_str.of_item("n").of_deref().of_get("a") |
See also
© 2003-2011 Desta, Ltd. All rights reserved. | SupportDesk |