Skip to content

Instantly share code, notes, and snippets.

@FROGGS
Created February 23, 2015 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FROGGS/ae724e5dcf4a2fe902fe to your computer and use it in GitHub Desktop.
Save FROGGS/ae724e5dcf4a2fe902fe to your computer and use it in GitHub Desktop.
diff --git a/lib/NativeCall.pm b/lib/NativeCall.pm
index 5c3c0c5..7fd76b1 100644
--- a/lib/NativeCall.pm
+++ b/lib/NativeCall.pm
@@ -65,7 +65,63 @@ sub return_hash_for(Signature $s, &r?, :$with-typeobj) {
$result
}
-my native long is repr("P6int") is Int is ctype("long") is export(:types, :DEFAULT) { };
+my native long is Int is ctype("long") is repr("P6int") is export(:types, :DEFAULT) { };
+my native longlong is Int is ctype("longlong") is repr("P6int") is export(:types, :DEFAULT) { };
+my class void is repr('CPointer') is export(:types, :DEFAULT) { };
+# Expose a Pointer class for working with raw pointers.
+my class Pointer is repr('CPointer') is export(:types, :DEFAULT) { };
+
+# need to introduce the roles in there in an augment, because you can't
+# inherit from types that haven't been properly composed.
+use MONKEY_TYPING;
+augment class Pointer {
+ method of() { void }
+
+ method ^name() { 'Pointer' }
+
+ multi method new() {
+ self.CREATE()
+ }
+ multi method new(int $addr) {
+ nqp::box_i($addr, ::?CLASS)
+ }
+ multi method new(Int $addr) {
+ nqp::box_i(nqp::unbox_i(nqp::decont($addr)), ::?CLASS)
+ }
+
+ method Numeric(::?CLASS:D:) { self.Int }
+ method Int(::?CLASS:D:) {
+ nqp::p6box_i(nqp::unbox_i(nqp::decont(self)))
+ }
+
+ method deref(::?CLASS:D \ptr:) { nativecast(void, ptr) }
+
+ multi method gist(::?CLASS:U:) { '(' ~ self.^name ~ ')' }
+ multi method gist(::?CLASS:D:) {
+ if self.Int -> $addr {
+ self.^name ~ '<' ~ $addr.fmt('%#x') ~ '>'
+ }
+ else {
+ self.^name ~ '<NULL>'
+ }
+ }
+
+ multi method perl(::?CLASS:U:) { self.^name }
+ multi method perl(::?CLASS:D:) { self.^name ~ '.new(' ~ self.Int ~ ')' }
+
+ my role TypedPointer[::TValue = void] is Pointer is repr('CPointer') {
+ method of() { ::TValue }
+ method ^name() { 'Pointer[' ~ ::TValue.^name ~ ']' }
+ method deref(::?CLASS:D \ptr:) { nativecast(::TValue, ptr) }
+ }
+ multi method PARAMETERIZE_TYPE(Mu:U \t) {
+ die "A typed pointer can only hold integers, numbers, strings, CStructs, CPointers or CArrays (not {t.^name})"
+ unless t ~~ Int || t ~~ Num || t === Str || t.REPR eq 'CStruct' | 'CUnion' | 'CPPStruct' | 'CPointer' | 'CArray';
+ my \typed := TypedPointer[t];
+ typed.HOW.make_pun(typed);
+ }
+}
+my constant OpaquePointer is export(:types, :DEFAULT) = Pointer;
# Gets the NCI type code to use based on a given Perl 6 type.
my %type_map =
@@ -96,8 +152,8 @@ sub type_code_for(Mu ::T) {
# the REPR of a Buf or Blob type object is Uninstantiable, so
# needs an extra special case here that isn't covered in the
# hash lookup above.
- return 'vmarray'
- if T ~~ Blob;
+ return 'vmarray' if T ~~ Blob;
+ return 'cpointer' if T ~~ Pointer;
die "Unknown type {T.^name} used in native call.\n" ~
"If you want to pass a struct, be sure to use the CStruct representation.\n" ~
"If you want to pass an array, be sure to use the CArray type.";
@@ -170,34 +226,6 @@ my role NativeCallEncoded[$name] {
method native_call_encoded() { $name };
}
-# Expose an OpaquePointer class for working with raw pointers.
-my class OpaquePointer is export(:types, :DEFAULT) is repr('CPointer') {
- multi method new() {
- self.CREATE()
- }
- multi method new(int $addr) {
- nqp::box_i($addr, OpaquePointer)
- }
- multi method new(Int $addr) {
- nqp::box_i(nqp::unbox_i(nqp::decont($addr)), OpaquePointer)
- }
- method Int(OpaquePointer:D:) {
- nqp::p6box_i(nqp::unbox_i(nqp::decont(self)))
- }
- method Numeric(OpaquePointer:D:) { self.Int }
- multi method gist(OpaquePointer:U:) { '(OpaquePointer)' }
- multi method gist(OpaquePointer:D:) {
- if self.Int -> $addr {
- 'OpaquePointer<' ~ $addr.fmt('%#x') ~ '>'
- }
- else {
- 'OpaquePointer<NULL>'
- }
- }
- multi method perl(OpaquePointer:U:) { 'OpaquePointer' }
- multi method perl(OpaquePointer:D:) { 'OpaquePointer.new(' ~ self.Int ~ ')' }
-}
-
# CArray class, used to represent C arrays.
my class CArray is export(:types, :DEFAULT) is repr('CArray') is array_type(OpaquePointer) { };
diff --git a/t/04-nativecall/04-pointers.t b/t/04-nativecall/04-pointers.t
index dd416e8..0bdad20 100644
--- a/t/04-nativecall/04-pointers.t
+++ b/t/04-nativecall/04-pointers.t
@@ -8,8 +8,8 @@ plan 10;
compile_test_lib('04-pointers');
-sub ReturnSomePointer() returns OpaquePointer is native("./04-pointers") { * }
-sub CompareSomePointer(OpaquePointer) returns int32 is native("./04-pointers") { * }
+sub ReturnSomePointer() returns Pointer is native("./04-pointers") { * }
+sub CompareSomePointer(Pointer) returns int32 is native("./04-pointers") { * }
my $x = ReturnSomePointer();
my int $a = 4321;
@@ -18,9 +18,9 @@ ok CompareSomePointer($x), 'Got passed back the pointer I returned';
ok $x, 'Non-NULL pointer is trueish';
ok $x.Int, 'Calling .Int on non-NULL pointer is trueish';
ok +$x, 'Calling prefix:<+> on non-NULL pointer is trueish';
-is +$x.perl.EVAL, +$x, 'OpaquePointer roundtrips okay using .perl and EVAL';
-is OpaquePointer.new.gist, 'OpaquePointer<NULL>', 'OpaquePointer.new gistifies to "OpaquePointer<NULL>"';
-is OpaquePointer.new(0).gist, 'OpaquePointer<NULL>', 'OpaquePointer.new(0) gistifies to "OpaquePointer<NULL>"';
-is OpaquePointer.new(1234).gist, 'OpaquePointer<0x4d2>', 'OpaquePointer.new(1234) gistifies to "OpaquePointer<0x4d2>"';
-is OpaquePointer.new($a).gist, 'OpaquePointer<0x10e1>', 'OpaquePointer.new accepts a native int too';
-is OpaquePointer.gist, '(OpaquePointer)', 'The OpaquePointer type object gistifies ot "OpaquePointer"';
+is +$x.perl.EVAL, +$x, 'Pointer roundtrips okay using .perl and EVAL';
+is Pointer.new.gist, 'Pointer<NULL>', 'Pointer.new gistifies to "Pointer<NULL>"';
+is Pointer.new(0).gist, 'Pointer<NULL>', 'Pointer.new(0) gistifies to "Pointer<NULL>"';
+is Pointer.new(1234).gist, 'Pointer<0x4d2>', 'Pointer.new(1234) gistifies to "Pointer<0x4d2>"';
+is Pointer.new($a).gist, 'Pointer<0x10e1>', 'Pointer.new accepts a native int too';
+is Pointer.gist, '(Pointer)', 'The Pointer type object gistifies ot "Pointer"';
diff --git a/t/04-nativecall/05-arrays.t b/t/04-nativecall/05-arrays.t
index a0a8674..d50cdd6 100644
--- a/t/04-nativecall/05-arrays.t
+++ b/t/04-nativecall/05-arrays.t
@@ -42,8 +42,8 @@ compile_test_lib('05-arrays');
}
{
- my @arr := CArray[OpaquePointer].new;
- @arr[1] = OpaquePointer.new;
+ my @arr := CArray[Pointer].new;
+ @arr[1] = Pointer.new;
my $x = @arr[0];
pass 'getting uninitialized element in managed array';
}
diff --git a/t/04-nativecall/07-writebarrier.t b/t/04-nativecall/07-writebarrier.t
index a61d4bd..361f743 100644
--- a/t/04-nativecall/07-writebarrier.t
+++ b/t/04-nativecall/07-writebarrier.t
@@ -24,7 +24,7 @@ class Structy is repr('CStruct') {
sub make_ptr() returns IntPtr is native('./07-writebarrier') { * }
sub array_twiddle(CArray[IntPtr] $a) is native('./07-writebarrier') { * }
sub struct_twiddle(Structy $s) is native('./07-writebarrier') { * }
-sub dummy(CArray[OpaquePointer] $a) is native('./07-writebarrier') { * }
+sub dummy(CArray[Pointer] $a) is native('./07-writebarrier') { * }
sub save_ref(Structy $s) is native('./07-writebarrier') { * }
sub atadistance() is native('./07-writebarrier') { * }
diff --git a/t/04-nativecall/09-nativecast.t b/t/04-nativecall/09-nativecast.t
index aab910a..27c4d3e 100644
--- a/t/04-nativecall/09-nativecast.t
+++ b/t/04-nativecall/09-nativecast.t
@@ -8,33 +8,33 @@ plan(9);
compile_test_lib('09-nativecast');
-sub ReturnArray() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnArray() returns Pointer is native('./09-nativecast') { * }
my $carray = nativecast(CArray[uint32], ReturnArray());
is $carray[0..2], (1, 2, 3), 'casting int * to CArray[uint32] works';
-sub ReturnStruct() returns OpaquePointer is native('./09-nativecast') { * };
+sub ReturnStruct() returns Pointer is native('./09-nativecast') { * };
class CUTE is repr('CStruct') {
has int32 $.i;
}
is nativecast(CUTE, ReturnStruct()).i, 100, 'casting to CStruct works';
-sub ReturnInt() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnInt() returns Pointer is native('./09-nativecast') { * }
is nativecast(int32, ReturnInt()), 101, 'casting to int32 works';
-sub ReturnShort() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnShort() returns Pointer is native('./09-nativecast') { * }
is nativecast(int16, ReturnShort()), 102, 'casting to int16 works';
-sub ReturnByte() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnByte() returns Pointer is native('./09-nativecast') { * }
is nativecast(int8, ReturnByte()), -103, 'casting to int8 works';
-sub ReturnDouble() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnDouble() returns Pointer is native('./09-nativecast') { * }
is_approx nativecast(num64, ReturnDouble()), 99.9e0, 'casting to num64 works';
-sub ReturnFloat() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnFloat() returns Pointer is native('./09-nativecast') { * }
is_approx nativecast(num32, ReturnFloat()), -4.5e0, 'casting to num32 works';
-sub ReturnString() returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnString() returns Pointer is native('./09-nativecast') { * }
is nativecast(str, ReturnString()), "epic cuteness", 'casting to str works';
-sub ReturnNullString returns OpaquePointer is native('./09-nativecast') { * }
+sub ReturnNullString returns Pointer is native('./09-nativecast') { * }
nok nativecast(str, ReturnNullString()).defined, 'casting null pointer to str';
diff --git a/t/04-nativecall/12-sizeof.t b/t/04-nativecall/12-sizeof.t
index ed618cc..864d3ae 100644
--- a/t/04-nativecall/12-sizeof.t
+++ b/t/04-nativecall/12-sizeof.t
@@ -45,10 +45,10 @@ sub SizeofInt() returns int32 is native('./12-sizeof') { * }
sub SizeofLng() returns int32 is native('./12-sizeof') { * }
sub SizeofPtr() returns int32 is native('./12-sizeof') { * }
-is nativesizeof(Foo), SizeofFoo(), 'sizeof(Foo)';
-is nativesizeof(Bar), SizeofBar(), 'sizeof(Bar)';
-is nativesizeof(Baz), SizeofBaz(), 'sizeof(Baz)';
-is nativesizeof(Buz), SizeofBuz(), 'sizeof(Buz)';
-is nativesizeof(int32), SizeofInt(), 'sizeof(int)';
-is nativesizeof(long), SizeofLng(), 'sizeof(long)';
-is nativesizeof(OpaquePointer), SizeofPtr(), 'sizeof(void *)';
+is nativesizeof(Foo), SizeofFoo(), 'sizeof(Foo)';
+is nativesizeof(Bar), SizeofBar(), 'sizeof(Bar)';
+is nativesizeof(Baz), SizeofBaz(), 'sizeof(Baz)';
+is nativesizeof(Buz), SizeofBuz(), 'sizeof(Buz)';
+is nativesizeof(int32), SizeofInt(), 'sizeof(int)';
+is nativesizeof(long), SizeofLng(), 'sizeof(long)';
+is nativesizeof(Pointer), SizeofPtr(), 'sizeof(void *)';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment