54
54
import static com .oracle .graal .python .util .PythonUtils .ARRAY_ACCESSOR_SWAPPED ;
55
55
import static com .oracle .graal .python .util .PythonUtils .TS_ENCODING ;
56
56
import static com .oracle .graal .python .util .PythonUtils .toTruffleStringUncached ;
57
+ import static com .oracle .graal .python .util .PythonUtils .tsLiteral ;
57
58
58
59
import java .util .List ;
59
60
70
71
import com .oracle .graal .python .builtins .modules .ctypes .StgDictBuiltins .PyTypeStgDictNode ;
71
72
import com .oracle .graal .python .builtins .modules .ctypes .memory .Pointer ;
72
73
import com .oracle .graal .python .builtins .modules .ctypes .memory .PointerNodes ;
74
+ import com .oracle .graal .python .builtins .modules .ctypes .memory .PointerReference ;
73
75
import com .oracle .graal .python .builtins .objects .PNone ;
74
76
import com .oracle .graal .python .builtins .objects .buffer .PythonBufferAccessLibrary ;
75
77
import com .oracle .graal .python .builtins .objects .bytes .BytesNodes .ToBytesWithoutFrameNode ;
76
78
import com .oracle .graal .python .builtins .objects .bytes .PBytesLike ;
79
+ import com .oracle .graal .python .builtins .objects .capsule .PyCapsule ;
77
80
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes .GetInternalByteArrayNode ;
78
81
import com .oracle .graal .python .builtins .objects .ints .PInt ;
79
82
import com .oracle .graal .python .builtins .objects .str .StringUtils .SimpleTruffleStringFormatNode ;
90
93
import com .oracle .graal .python .nodes .function .builtins .PythonTernaryBuiltinNode ;
91
94
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
92
95
import com .oracle .graal .python .nodes .util .CastToTruffleStringNode ;
96
+ import com .oracle .graal .python .runtime .PythonContext ;
93
97
import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
94
98
import com .oracle .truffle .api .CompilerDirectives ;
95
99
import com .oracle .truffle .api .dsl .Bind ;
@@ -395,7 +399,7 @@ protected abstract static class SetFuncNode extends Node {
395
399
abstract Object execute (VirtualFrame frame , FieldSet setfunc , Pointer ptr , Object value , int size );
396
400
397
401
@ Specialization (guards = "setfunc == b_set || setfunc == B_set" )
398
- Object b_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
402
+ static Object b_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
399
403
@ Bind ("this" ) Node inliningTarget ,
400
404
@ Shared @ Cached PyLongAsLongNode asLongNode ,
401
405
@ Shared @ Cached PointerNodes .WriteByteNode writeByteNode ) {
@@ -405,7 +409,7 @@ Object b_set(VirtualFrame frame, @SuppressWarnings("unused") FieldSet setfunc, P
405
409
}
406
410
407
411
@ Specialization (guards = "setfunc == h_set || setfunc == H_set" )
408
- Object h_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
412
+ static Object h_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
409
413
@ Bind ("this" ) Node inliningTarget ,
410
414
@ Shared @ Cached PyLongAsLongNode asLongNode ,
411
415
@ Shared @ Cached PointerNodes .WriteShortNode writeShortNode ) {
@@ -415,7 +419,7 @@ Object h_set(VirtualFrame frame, @SuppressWarnings("unused") FieldSet setfunc, P
415
419
}
416
420
417
421
@ Specialization (guards = "setfunc == h_set_sw || setfunc == H_set_sw" )
418
- Object h_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
422
+ static Object h_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
419
423
@ Bind ("this" ) Node inliningTarget ,
420
424
@ Shared @ Cached PyLongAsLongNode asLongNode ,
421
425
@ Shared @ Cached PointerNodes .WriteShortNode writeShortNode ) {
@@ -426,7 +430,7 @@ Object h_set_sw(VirtualFrame frame, @SuppressWarnings("unused") FieldSet setfunc
426
430
}
427
431
428
432
@ Specialization (guards = "setfunc == i_set || setfunc == I_set" )
429
- Object i_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
433
+ static Object i_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
430
434
@ Bind ("this" ) Node inliningTarget ,
431
435
@ Shared @ Cached PyLongAsLongNode asLongNode ,
432
436
@ Shared @ Cached PointerNodes .WriteIntNode writeIntNode ) {
@@ -436,7 +440,7 @@ Object i_set(VirtualFrame frame, @SuppressWarnings("unused") FieldSet setfunc, P
436
440
}
437
441
438
442
@ Specialization (guards = "setfunc == i_set_sw || setfunc == I_set_sw" )
439
- Object i_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
443
+ static Object i_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
440
444
@ Bind ("this" ) Node inliningTarget ,
441
445
@ Shared @ Cached PyLongAsLongNode asLongNode ,
442
446
@ Shared @ Cached PointerNodes .WriteIntNode writeIntNode ) {
@@ -477,7 +481,7 @@ static Object bool_set(VirtualFrame frame, @SuppressWarnings("unused") FieldSet
477
481
}
478
482
479
483
@ Specialization (guards = "setfunc == l_set || setfunc == L_set" )
480
- Object l_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
484
+ static Object l_set (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
481
485
@ Bind ("this" ) Node inliningTarget ,
482
486
@ Shared @ Cached PyLongAsLongNode asLongNode ,
483
487
@ Shared @ Cached PointerNodes .WriteLongNode writeLongNode ) {
@@ -487,7 +491,7 @@ Object l_set(VirtualFrame frame, @SuppressWarnings("unused") FieldSet setfunc, P
487
491
}
488
492
489
493
@ Specialization (guards = "setfunc == l_set_sw || setfunc == L_set_sw" )
490
- Object l_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
494
+ static Object l_set_sw (VirtualFrame frame , @ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
491
495
@ Bind ("this" ) Node inliningTarget ,
492
496
@ Shared @ Cached PyLongAsLongNode asLongNode ,
493
497
@ Shared @ Cached PointerNodes .WriteLongNode writeLongNode ) {
@@ -550,7 +554,7 @@ static Object O_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, O
550
554
}
551
555
552
556
@ Specialization (guards = "setfunc == c_set" )
553
- Object c_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
557
+ static Object c_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
554
558
@ Bind ("this" ) Node inliningTarget ,
555
559
@ Cached GetInternalByteArrayNode getBytes ,
556
560
@ Shared @ Cached PointerNodes .WriteByteNode writeByteNode ,
@@ -576,7 +580,7 @@ Object c_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
576
580
577
581
/* u - a single wchar_t character */
578
582
@ Specialization (guards = "setfunc == u_set" )
579
- Object u_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
583
+ static Object u_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
580
584
@ Bind ("this" ) Node inliningTarget ,
581
585
@ Cached CastToTruffleStringNode toString ,
582
586
@ Cached TruffleString .SwitchEncodingNode switchEncodingNode ,
@@ -596,7 +600,7 @@ Object u_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
596
600
}
597
601
598
602
@ Specialization (guards = "setfunc == U_set" )
599
- Object U_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , int size ,
603
+ static Object U_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , int size ,
600
604
@ Bind ("this" ) Node inliningTarget ,
601
605
@ Cached CastToTruffleStringNode toString ,
602
606
@ Cached TruffleString .SwitchEncodingNode switchEncodingNode ,
@@ -617,7 +621,7 @@ Object U_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
617
621
}
618
622
619
623
@ Specialization (guards = "setfunc == s_set" )
620
- Object s_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , int length ,
624
+ static Object s_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , int length ,
621
625
@ Bind ("this" ) Node inliningTarget ,
622
626
@ Cached ToBytesWithoutFrameNode getBytes ,
623
627
@ Shared @ Cached PointerNodes .WriteBytesNode writeBytesNode ,
@@ -642,19 +646,20 @@ Object s_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
642
646
}
643
647
644
648
@ Specialization (guards = "setfunc == z_set" )
645
- Object z_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
649
+ static Object z_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
646
650
@ Bind ("this" ) Node inliningTarget ,
647
651
@ Shared @ Cached PyLongCheckNode longCheckNode ,
648
652
@ Shared @ Cached PointerNodes .PointerFromLongNode pointerFromLongNode ,
649
653
@ CachedLibrary (limit = "1" ) PythonBufferAccessLibrary bufferLib ,
650
654
@ Shared @ Cached PointerNodes .WritePointerNode writePointerNode ,
651
- @ Shared @ Cached PRaiseNode raiseNode ) {
655
+ @ Shared @ Cached PRaiseNode raiseNode ,
656
+ @ Shared @ Cached PythonObjectFactory factory ) {
652
657
if (value == PNone .NONE ) {
653
658
writePointerNode .execute (inliningTarget , ptr , Pointer .NULL );
654
659
return PNone .NONE ;
655
660
} else if (longCheckNode .execute (value )) {
656
661
writePointerNode .execute (inliningTarget , ptr , pointerFromLongNode .execute (inliningTarget , value ));
657
- return value ;
662
+ return PNone . NONE ;
658
663
}
659
664
if (PGuards .isPBytes (value )) {
660
665
int len = bufferLib .getBufferLength (value );
@@ -663,27 +668,33 @@ Object z_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
663
668
/* ptr is a char**, we need to add the indirection */
664
669
Pointer valuePtr = Pointer .bytes (bytes );
665
670
writePointerNode .execute (inliningTarget , ptr , valuePtr );
671
+ /*
672
+ * We make a copy of the memory, so we need to register a destructor to free the
673
+ * memory in case it goes to native.
674
+ */
675
+ new PointerReference (value , valuePtr , PythonContext .get (inliningTarget ).getSharedFinalizer ());
666
676
return value ;
667
677
}
668
678
throw raiseNode .raise (TypeError , ErrorMessages .BYTES_OR_INT_ADDR_EXPECTED_INSTEAD_OF_P , value );
669
679
}
670
680
671
681
@ Specialization (guards = "setfunc == Z_set" )
672
- Object Z_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
682
+ static Object Z_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
673
683
@ Bind ("this" ) Node inliningTarget ,
674
684
@ Cached CastToTruffleStringNode toString ,
675
685
@ Shared @ Cached PyLongCheckNode longCheckNode ,
676
686
@ Shared @ Cached PointerNodes .PointerFromLongNode pointerFromLongNode ,
677
687
@ Cached TruffleString .SwitchEncodingNode switchEncodingNode ,
678
688
@ Cached TruffleString .CopyToByteArrayNode copyToByteArrayNode ,
679
689
@ Shared @ Cached PointerNodes .WritePointerNode writePointerNode ,
680
- @ Shared @ Cached PRaiseNode raiseNode ) { // CTYPES_UNICODE
690
+ @ Shared @ Cached PRaiseNode raiseNode ,
691
+ @ Shared @ Cached PythonObjectFactory factory ) { // CTYPES_UNICODE
681
692
if (value == PNone .NONE ) {
682
693
writePointerNode .execute (inliningTarget , ptr , Pointer .NULL );
683
694
return PNone .NONE ;
684
695
} else if (longCheckNode .execute (value )) {
685
696
writePointerNode .execute (inliningTarget , ptr , pointerFromLongNode .execute (inliningTarget , value ));
686
- return value ;
697
+ return PNone . NONE ;
687
698
}
688
699
if (!PGuards .isString (value )) {
689
700
throw raiseNode .raise (TypeError , ErrorMessages .UNICODE_STR_OR_INT_ADDR_EXPECTED_INSTEAD_OF_P , value );
@@ -697,11 +708,11 @@ Object Z_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
697
708
/* ptr is a char**, we need to add the indirection */
698
709
Pointer valuePtr = Pointer .bytes (bytes );
699
710
writePointerNode .execute (inliningTarget , ptr , valuePtr );
700
- return str ;
711
+ return createPyMemCapsule ( valuePtr , factory ) ;
701
712
}
702
713
703
714
@ Specialization (guards = "setfunc == P_set" )
704
- Object P_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
715
+ static Object P_set (@ SuppressWarnings ("unused" ) FieldSet setfunc , Pointer ptr , Object value , @ SuppressWarnings ("unused" ) int size ,
705
716
@ Bind ("this" ) Node inliningTarget ,
706
717
@ Shared @ Cached PyLongCheckNode longCheckNode ,
707
718
@ Shared @ Cached PointerNodes .PointerFromLongNode pointerFromLongNode ,
@@ -722,11 +733,18 @@ Object P_set(@SuppressWarnings("unused") FieldSet setfunc, Pointer ptr, Object v
722
733
723
734
@ SuppressWarnings ("unused" )
724
735
@ Fallback
725
- Object error (VirtualFrame frame , FieldSet setfunc , Pointer ptr , Object value , int size ) {
736
+ static Object error (VirtualFrame frame , FieldSet setfunc , Pointer ptr , Object value , int size ) {
726
737
CompilerDirectives .transferToInterpreterAndInvalidate ();
727
738
throw PRaiseNode .getUncached ().raise (NotImplementedError , toTruffleStringUncached ("Field setter %s is not supported yet." ), setfunc .name ());
728
739
}
729
740
741
+ private static TruffleString CTYPES_CFIELD_CAPSULE_NAME_PYMEM = tsLiteral ("_ctypes/cfield.c pymem" );
742
+
743
+ private static PyCapsule createPyMemCapsule (Pointer pointer , PythonObjectFactory factory ) {
744
+ PyCapsule capsule = factory .createCapsule (pointer , CTYPES_CFIELD_CAPSULE_NAME_PYMEM , null );
745
+ new PointerReference (capsule , pointer , PythonContext .get (factory ).getSharedFinalizer ());
746
+ return capsule ;
747
+ }
730
748
}
731
749
732
750
@ ImportStatic (FieldGet .class )
@@ -897,7 +915,7 @@ static double f_get_sw(@SuppressWarnings("unused") FieldGet getfunc, Pointer ptr
897
915
}
898
916
899
917
@ Specialization (guards = "getfunc == O_get" )
900
- Object O_get (@ SuppressWarnings ("unused" ) FieldGet getfunc , Pointer ptr , @ SuppressWarnings ("unused" ) int size ,
918
+ static Object O_get (@ SuppressWarnings ("unused" ) FieldGet getfunc , Pointer ptr , @ SuppressWarnings ("unused" ) int size ,
901
919
@ Bind ("this" ) Node inliningTarget ,
902
920
@ Shared @ Cached PointerNodes .ReadPointerNode readPointerNode ,
903
921
@ Cached PointerNodes .ReadPythonObject readPythonObject ,
0 commit comments