FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonnet-rawsvnmig/pythonnet/src/runtime/nativecall.cs at master · pythonnet/pythonnet-rawsvnmig · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
This repository was archived by the owner on Jun 4, 2019. It is now read-only.
pythonnet
/
pythonnet-rawsvnmig
Public archive
Notifications
You must be signed in to change notification settings
Fork
1
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonnet-rawsvnmig
/
pythonnet
/
src
/
runtime
/
nativecall.cs
Copy path
More file actions
More file actions
Latest commit
History
History
History
166 lines (122 loc) · 5.84 KB
Breadcrumbs
pythonnet-rawsvnmig
/
pythonnet
/
src
/
runtime
/
nativecall.cs
Copy path
File metadata and controls
166 lines (122 loc) · 5.84 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// ==========================================================================
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
// ==========================================================================
using
System
;
using
System
.
Threading
;
using
System
.
Runtime
.
InteropServices
;
using
System
.
Collections
;
using
System
.
Reflection
;
using
System
.
Reflection
.
Emit
;
namespace
Python
.
Runtime
{
/// <summary>
/// Provides support for calling native code indirectly through
/// function pointers. Most of the important parts of the Python
/// C API can just be wrapped with p/invoke, but there are some
/// situations (specifically, calling functions through Python
/// type structures) where we need to call functions indirectly.
///
/// This class uses Reflection.Emit to generate IJW thunks that
/// support indirect calls to native code using various common
/// call signatures. This is mainly a workaround for the fact
/// that you can't spell an indirect call in C# (but can in IL).
///
/// Another approach that would work is for this to be turned
/// into a separate utility program that could be run during the
/// build process to generate the thunks as a separate assembly
/// that could then be referenced by the main Python runtime.
/// </summary>
internal
class
NativeCall
{
static
AssemblyBuilder
aBuilder
;
static
ModuleBuilder
mBuilder
;
public
static
INativeCall
Impl
;
static
NativeCall
(
)
{
// The static constructor is responsible for generating the
// assembly and the methods that implement the IJW thunks.
//
// To do this, we actually use reflection on the INativeCall
// interface (defined below) and generate the required thunk
// code based on the method signatures.
AssemblyName
aname
=
new
AssemblyName
(
)
;
aname
.
Name
=
"e__NativeCall_Assembly"
;
AssemblyBuilderAccess
aa
=
AssemblyBuilderAccess
.
Run
;
aBuilder
=
Thread
.
GetDomain
(
)
.
DefineDynamicAssembly
(
aname
,
aa
)
;
mBuilder
=
aBuilder
.
DefineDynamicModule
(
"e__NativeCall_Module"
)
;
TypeAttributes
ta
=
TypeAttributes
.
Public
;
TypeBuilder
tBuilder
=
mBuilder
.
DefineType
(
"e__NativeCall"
,
ta
)
;
Type
iType
=
typeof
(
INativeCall
)
;
tBuilder
.
AddInterfaceImplementation
(
iType
)
;
// Use reflection to loop over the INativeCall interface methods,
// calling GenerateThunk to create a managed thunk for each one.
foreach
(
MethodInfo
method
in
iType
.
GetMethods
(
)
)
{
GenerateThunk
(
tBuilder
,
method
)
;
}
Type
theType
=
tBuilder
.
CreateType
(
)
;
Impl
=
(
INativeCall
)
Activator
.
CreateInstance
(
theType
)
;
}
private
static
void
GenerateThunk
(
TypeBuilder
tb
,
MethodInfo
method
)
{
ParameterInfo
[
]
pi
=
method
.
GetParameters
(
)
;
int
count
=
pi
.
Length
;
int
argc
=
count
-
1
;
Type
[
]
args
=
new
Type
[
count
]
;
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
args
[
i
]
=
pi
[
i
]
.
ParameterType
;
}
MethodBuilder
mb
=
tb
.
DefineMethod
(
method
.
Name
,
MethodAttributes
.
Public
|
MethodAttributes
.
Virtual
,
method
.
ReturnType
,
args
)
;
// Build the method signature for the actual native function.
// This is essentially the signature of the wrapper method
// minus the first argument (the passed in function pointer).
Type
[
]
nargs
=
new
Type
[
argc
]
;
for
(
int
i
=
1
;
i
<
count
;
i
++
)
{
nargs
[
(
i
-
1
)
]
=
args
[
i
]
;
}
// IL generation: the (implicit) first argument of the method
// is the 'this' pointer and the second is the function pointer.
// This code pushes the real args onto the stack, followed by
// the function pointer, then the calli opcode to make the call.
ILGenerator
il
=
mb
.
GetILGenerator
(
)
;
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
il
.
Emit
(
OpCodes
.
Ldarg_S
,
(
i
+
2
)
)
;
}
il
.
Emit
(
OpCodes
.
Ldarg_1
)
;
il
.
EmitCalli
(
OpCodes
.
Calli
,
CallingConvention
.
Cdecl
,
method
.
ReturnType
,
nargs
)
;
il
.
Emit
(
OpCodes
.
Ret
)
;
tb
.
DefineMethodOverride
(
mb
,
method
)
;
return
;
}
public
static
void
Void_Call_1
(
IntPtr
fp
,
IntPtr
a1
)
{
Impl
.
Void_Call_1
(
fp
,
a1
)
;
}
public
static
IntPtr
Call_3
(
IntPtr
fp
,
IntPtr
a1
,
IntPtr
a2
,
IntPtr
a3
)
{
return
Impl
.
Call_3
(
fp
,
a1
,
a2
,
a3
)
;
}
public
static
int
Int_Call_3
(
IntPtr
fp
,
IntPtr
a1
,
IntPtr
a2
,
IntPtr
a3
)
{
return
Impl
.
Int_Call_3
(
fp
,
a1
,
a2
,
a3
)
;
}
}
/// <summary>
/// Defines native call signatures to be generated by NativeCall.
/// </summary>
public
interface
INativeCall
{
void
Void_Call_0
(
IntPtr
funcPtr
)
;
void
Void_Call_1
(
IntPtr
funcPtr
,
IntPtr
arg1
)
;
int
Int_Call_3
(
IntPtr
funcPtr
,
IntPtr
t
,
IntPtr
n
,
IntPtr
v
)
;
IntPtr
Call_3
(
IntPtr
funcPtr
,
IntPtr
a1
,
IntPtr
a2
,
IntPtr
a3
)
;
}
}
Back
|
FazBrowse Home
|
New Git URL