cvsuser 04/02/05 05:09:41
Modified: classes unmanagedstruct.pmc
docs/pmc struct.pod
src nci_test.c
t/pmc nci.t
Log:
add DATATYPE_CSTR to struct handling
* please rebuild test lib:
make libnci.so
Revision Changes Path
1.28 +64 -1 parrot/classes/unmanagedstruct.pmc
Index: unmanagedstruct.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/unmanagedstruct.pmc,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -w -r1.27 -r1.28
--- unmanagedstruct.pmc 5 Feb 2004 11:07:35 -0000 1.27
+++ unmanagedstruct.pmc 5 Feb 2004 13:09:30 -0000 1.28
@@ -1,7 +1,7 @@
/*
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: unmanagedstruct.pmc,v 1.27 2004/02/05 11:07:35 leo Exp $
+ * $Id: unmanagedstruct.pmc,v 1.28 2004/02/05 13:09:30 leo Exp $
* Overview:
* PMC class to hold structs that parrot's not responsible for
* disposing of.
@@ -123,6 +123,24 @@
return -1.0;
}
+static STRING*
+ret_string(Parrot_Interp interpreter, char *p, int type)
+{
+ char *cstr;
+ size_t len;
+
+ switch (type) {
+ case enum_type_cstr:
+ cstr = *(char **) p;
+ len = strlen(cstr);
+ return string_make(interpreter, cstr, len, NULL,
+ PObj_external_FLAG, NULL);
+ default:
+ internal_exception(1, "returning unhandled string type in struct");
+ }
+ return NULL;
+}
+
static void
set_int(char *p, int type, INTVAL value)
{
@@ -163,6 +181,27 @@
case enum_type_double:
*(double*) p = (double) value;
break;
+ default:
+ internal_exception(1, "setting unhandled float type in struct");
+ break;
+ }
+}
+
+static void
+set_string(char *p, int type, STRING* value)
+{
+ char *cstr;
+ switch (type) {
+ case enum_type_cstr:
+ /* XXX assumes 0-terminate C-string here
+ * we can't use string_to_cstring easily
+ */
+ cstr = value->strstart;
+ *(char **) p = cstr;
+ break;
+ default:
+ internal_exception(1, "setting unhandled string type in struct");
+ break;
}
}
@@ -323,6 +362,18 @@
return ret_float(p, type);
}
+ STRING* get_string_keyed_int (INTVAL key) {
+ int type;
+ char *p = char_offset_int(interpreter, pmc, key, &type);
+ return ret_string(interpreter, p, type);
+ }
+
+ STRING* get_string_keyed (PMC* key) {
+ int type;
+ char *p = char_offset_key(interpreter, pmc, key, &type);
+ return ret_string(interpreter, p, type);
+ }
+
INTVAL get_integer() {
return (INTVAL)*(INTVAL *)PMC_data(SELF);
}
@@ -377,6 +428,18 @@
int type;
char *p = char_offset_key(interpreter, pmc, key, &type);
set_float(p, type, value);
+ }
+
+ void set_string_keyed_int (INTVAL key, STRING* value) {
+ int type;
+ char *p = char_offset_int(interpreter, pmc, key, &type);
+ set_string(p, type, value);
+ }
+
+ void set_string_keyed (PMC *key, STRING* value) {
+ int type;
+ char *p = char_offset_key(interpreter, pmc, key, &type);
+ set_string(p, type, value);
}
}
1.3 +30 -3 parrot/docs/pmc/struct.pod
Index: struct.pod
===================================================================
RCS file: /cvs/public/parrot/docs/pmc/struct.pod,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -w -r1.2 -r1.3
--- struct.pod 5 Feb 2004 11:07:39 -0000 1.2
+++ struct.pod 5 Feb 2004 13:09:33 -0000 1.3
@@ -56,6 +56,7 @@
double d;
float f;
int i[4];
+ char *s;
};
can be declared with this initializer:
@@ -71,6 +72,9 @@
push P2, .DATATYPE_INT
push P2, 4 # 4 elem array
push P2, 0
+ push P2, .DATATYPE_CSTR
+ push P2, 0
+ push P2, 0
=head2 Named Structure Elements
@@ -104,6 +108,8 @@
sizeof I7, .DATATYPE_INT
mul I7, 4
add I6, I7
+ sizeof I7, .DATATYPE_CSTR
+ add I6, I7
set P5, I6 # allocate size
@@ -116,9 +122,8 @@
So for above example:
- set I6, P2[8] # offset of 3rd struct element i[4]
- sizeof I7, .DATATYPE_INT
- mul I7, 4
+ set I6, P2[11] # offset of 4rd struct element *s
+ sizeof I7, .DATATYPE_CSTR
add I6, I7 # I6 is now the total size
=head1 Accessing Structure Items
@@ -142,6 +147,28 @@
set I3, P5[2;3] # get i[3]
set P5["i"; 2] # set i[2] if initializer is an OrderedHash
+
+ set S0, P5[3] # get string at *s
+ set S0, P5["s"] # same
+
+=head2 Strings
+
+When passing a STRING to a structure that needs a 0-terminated
+C-string (char *s), then you have to provide the terminating NUL char
+in the string.
+
+ struct {
+ ...
+ char *s;
+ };
+
+ set P5["s"], "a string\x0"
+
+Please also note, that the C function currently gets a pointer to string
+memory, so any code that might trigger GC should be avoided (or GC turned off).
+Passing constant strings like above is safe though.
+
+ set P5["s"], S0 # S0 shouldn't move until function call
=head1 Passing A Structure to a C function
1.16 +14 -0 parrot/src/nci_test.c
Index: nci_test.c
===================================================================
RCS file: /cvs/public/parrot/src/nci_test.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -w -r1.15 -r1.16
--- nci_test.c 5 Feb 2004 10:24:14 -0000 1.15
+++ nci_test.c 5 Feb 2004 13:09:37 -0000 1.16
@@ -45,8 +45,11 @@
double d;
float f;
int i;
+ char *s;
} dfi;
dfi *sp = (dfi*) p;
+ puts(sp->s);
+ fflush(stdout);
return (int) (sp->d + sp->f + sp->i);
}
@@ -127,6 +130,17 @@
int i;
} t = {
10,
+ 20
+ };
+ return &t;
+ }
+ case 3:
+ {
+ static struct {
+ const char *c;
+ int i;
+ } t = {
+ "hello",
20
};
return &t;
1.22 +37 -2 parrot/t/pmc/nci.t
Index: nci.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/nci.t,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -w -r1.21 -r1.22
--- nci.t 5 Feb 2004 10:24:18 -0000 1.21
+++ nci.t 5 Feb 2004 13:09:40 -0000 1.22
@@ -1,4 +1,4 @@
-use Parrot::Test tests => 19;
+use Parrot::Test tests => 20;
use Parrot::Config;
print STDERR $PConfig{jitcpuarch}, " JIT CPU\n";
@@ -464,10 +464,38 @@
/
OUTPUT
+output_is(<<'CODE', <<'OUTPUT', "nci_p_i - char*");
+ loadlib P1, "libnci"
+ dlfunc P0, P1, "nci_pi", "pi"
+ # this test function returns a struct { char*; int }
+ set I5, 3
+ invoke
+ new P2, .PerlArray
+.include "datatypes.pasm"
+ push P2, .DATATYPE_CSTR
+ push P2, 0
+ push P2, 0
+ push P2, .DATATYPE_INT
+ push P2, 0
+ push P2, 0
+ assign P5, P2
+ set S0, P5[0]
+ print S0
+ print "\n"
+ set I0, P5[1]
+ print I0
+ print "\n"
+ end
+CODE
+hello
+20
+OUTPUT
+
output_is(<<'CODE', <<'OUTPUT', "nci_i_p");
loadlib P1, "libnci"
dlfunc P0, P1, "nci_ip", "ip"
- # this test function wants a struct { double d; float f; int i }
+ # this test function wants a struct
+ # { double d; float f; int i; char*}
# and returns the sum of these values
new P2, .PerlArray
.include "datatypes.pasm"
@@ -480,6 +508,9 @@
push P2, .DATATYPE_INT
push P2, 0 # 1 elem array
push P2, 0
+ push P2, .DATATYPE_CSTR
+ push P2, 0 # 1 elem array
+ push P2, 0
new P5, .ManagedStruct, P2
set I6, 0
sizeof I7, .DATATYPE_DOUBLE
@@ -488,16 +519,20 @@
add I6, I7
sizeof I7, .DATATYPE_INT
add I6, I7
+ sizeof I7, .DATATYPE_CSTR
+ add I6, I7
set P5, I6
set P5[0], 10.0
set P5[1], 4.0
set P5[2], 17
+ set P5[3], "hello from Parrot\x0"
set I5, 1
invoke
print I5
print "\n"
end
CODE
+hello from Parrot
31
OUTPUT