Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Better string support, including multiple encodings.

  • Loading branch information...
commit d22dd75a7f3abaf0485543cee634aefb9c52a34c 1 parent e293ff0
Jonathan Worthington authored
Showing with 45 additions and 7 deletions.
  1. +45 −7 lib/NativeCall.pm6
52 lib/NativeCall.pm6
View
@@ -4,18 +4,44 @@ module NativeCall;
# representation.
my class native_callsite is repr('NativeCall') { }
+# Maps a chosen string encoding to a type recognized by the native call engine.
+sub string_encoding_to_nci_type($enc) {
+ given $enc {
+ when 'utf8' { 'utf8str' }
+ when 'utf16' { 'utf16str' }
+ when 'ascii' { 'asciistr' }
+ default { die "Unknown string encoding for native call: $enc"; }
+ }
+}
+
# Builds a hash of type information for the specified parameter.
sub param_hash_for(Parameter $p) {
my Mu $result := nqp::hash();
- nqp::bindkey($result, 'type', nqp::unbox_s(type_code_for($p.type)));
+ my $type := $p.type();
+ if $type ~~ Str {
+ my $enc := $p.?native_call_encoded() || 'utf8';
+ nqp::bindkey($result, 'type', nqp::unbox_s(string_encoding_to_nci_type($enc)));
+ nqp::bindkey($result, 'free_str', nqp::unbox_i(1));
+ }
+ else {
+ nqp::bindkey($result, 'type', nqp::unbox_s(type_code_for($p.type)));
+ }
$result
}
# Builds a hash of type information for the specified return type.
-sub return_hash_for(Mu ::T) {
+sub return_hash_for(&r) {
my Mu $result := nqp::hash();
- nqp::bindkey($result, 'type',
- T =:= Mu ?? 'void' !! nqp::unbox_s(type_code_for(T)));
+ my $returns := &r.returns;
+ if $returns ~~ Str {
+ my $enc := &r.?native_call_encoded() || 'utf8';
+ nqp::bindkey($result, 'type', nqp::unbox_s(string_encoding_to_nci_type($enc)));
+ nqp::bindkey($result, 'free_str', nqp::unbox_i(0));
+ }
+ else {
+ nqp::bindkey($result, 'type',
+ $returns =:= Mu ?? 'void' !! nqp::unbox_s(type_code_for($returns)));
+ }
$result
}
@@ -29,8 +55,7 @@ my %type_map =
'num32' => 'float',
'num64' => 'double',
'num' => 'double',
- 'Num' => 'double',
- 'Str' => 'utf8str';
+ 'Num' => 'double';
sub type_code_for(Mu ::T) {
return %type_map{T.^name}
if %type_map.exists(T.^name);
@@ -59,7 +84,7 @@ my role Native[Routine $r, Str $libname] {
nqp::unbox_s($r.name), # symbol to call
nqp::unbox_s($conv), # calling convention
$arg_info,
- return_hash_for($r.returns));
+ return_hash_for($r));
$!setup = 1;
}
nqp::nativecall(nqp::p6decont($r.returns), self,
@@ -72,6 +97,11 @@ my role NativeCallingConvention[$name] {
method native_call_convention() { $name };
}
+# Role for carrying extra string encoding information.
+my role NativeCallEncoded[$name] {
+ method native_call_encoded() { $name };
+}
+
# Specifies that the routine is actually a native call, and gives
# the name of the library to load it from.
multi trait_mod:<is>(Routine $r, $libname, :$native!) is export {
@@ -82,3 +112,11 @@ multi trait_mod:<is>(Routine $r, $libname, :$native!) is export {
multi trait_mod:<is>(Routine $r, $name, :$nativeconv!) is export {
$r does NativeCallingConvention[$name];
}
+
+# Ways to specify how to marshall strings.
+multi trait_mod:<is>(Parameter $p, $name, :$encoded!) is export {
+ $p does NativeCallEncoded[$name];
+}
+multi trait_mod:<is>(Routine $p, $name, :$encoded!) is export {
+ $p does NativeCallEncoded[$name];
+}
Please sign in to comment.
Something went wrong with that request. Please try again.