vrpc 2.5.0 → 3.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +33 -56
- package/binding.gyp.no-auto +4 -26
- package/browser/vrpc.js +1 -1
- package/index.js +2 -2
- package/package.json +13 -17
- package/vrpc/VrpcAdapter.js +275 -233
- package/vrpc/VrpcAgent.js +204 -185
- package/vrpc/{VrpcRemote.js → VrpcClient.js} +295 -288
- package/vrpc/VrpcNative.js +307 -0
- package/vrpc/{vrpc.hpp → adapter.hpp} +1001 -1115
- package/vrpc/addon.cpp +5 -5
- package/vrpc/json.hpp +1769 -870
- package/vrpc/vrpc-agent-js +4 -4
- package/README.rst +0 -18
- package/third_party/include/catch.hpp +0 -12749
- package/third_party/install.sh +0 -22
- package/vrpc/VrpcLocal.js +0 -264
- package/vrpc/VrpcLocal.py +0 -171
- package/vrpc/__init__.py +0 -1
- package/vrpc/module.cpp +0 -183
package/third_party/install.sh
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
script_dir=$(dirname `[[ $0 = /* ]] && echo "$0" || echo "$PWD/${0#./}"`)
|
|
4
|
-
cd ${script_dir}
|
|
5
|
-
if [ $? -ne 0 ]; then
|
|
6
|
-
echo " Could not change directory to ${script_dir}"
|
|
7
|
-
exit 1;
|
|
8
|
-
fi
|
|
9
|
-
|
|
10
|
-
INSTALL_PREFIX=${script_dir}
|
|
11
|
-
mkdir -p build
|
|
12
|
-
mkdir -p include
|
|
13
|
-
pushd build
|
|
14
|
-
|
|
15
|
-
### CATCH (for testing) ###
|
|
16
|
-
|
|
17
|
-
if [ ! -f ${INSTALL_PREFIX}/include/catch.hpp ]; then
|
|
18
|
-
wget https://github.com/catchorg/Catch2/releases/download/v2.1.1/catch.hpp
|
|
19
|
-
cp catch.hpp ../include
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
popd
|
package/vrpc/VrpcLocal.js
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
__/\\\________/\\\____/\\\\\\\\\______/\\\\\\\\\\\\\_________/\\\\\\\\\_
|
|
3
|
-
__\/\\\_______\/\\\__/\\\///////\\\___\/\\\/////////\\\____/\\\////////__
|
|
4
|
-
__\//\\\______/\\\__\/\\\_____\/\\\___\/\\\_______\/\\\__/\\\/___________
|
|
5
|
-
___\//\\\____/\\\___\/\\\\\\\\\\\/____\/\\\\\\\\\\\\\/__/\\\_____________
|
|
6
|
-
____\//\\\__/\\\____\/\\\//////\\\____\/\\\/////////___\/\\\_____________
|
|
7
|
-
_____\//\\\/\\\_____\/\\\____\//\\\___\/\\\____________\//\\\____________
|
|
8
|
-
______\//\\\\\______\/\\\_____\//\\\__\/\\\_____________\///\\\__________
|
|
9
|
-
_______\//\\\_______\/\\\______\//\\\_\/\\\_______________\////\\\\\\\\\_
|
|
10
|
-
________\///________\///________\///__\///___________________\/////////__
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Non-intrusively binds code and provides access in form of asynchronous remote
|
|
14
|
-
procedure calls (RPC).
|
|
15
|
-
Author: Dr. Burkhard C. Heisen (https://github.com/bheisen/vrpc)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
19
|
-
Copyright (c) 2018 - 2021 Dr. Burkhard C. Heisen <burkhard.heisen@heisenware.com>.
|
|
20
|
-
|
|
21
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
22
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
23
|
-
in the Software without restriction, including without limitation the rights
|
|
24
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
25
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
26
|
-
furnished to do so, subject to the following conditions:
|
|
27
|
-
|
|
28
|
-
The above copyright notice and this permission notice shall be included in all
|
|
29
|
-
copies or substantial portions of the Software.
|
|
30
|
-
|
|
31
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
32
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
33
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
34
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
35
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
36
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
37
|
-
SOFTWARE.
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
const EventEmitter = require('events')
|
|
41
|
-
const crypto = require('crypto')
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Client capable of creating proxy objects and locally calling
|
|
45
|
-
* functions as provided through native addons.
|
|
46
|
-
*/
|
|
47
|
-
class VrpcLocal {
|
|
48
|
-
/**
|
|
49
|
-
* @constructor
|
|
50
|
-
* @param {Object} adapter An adapter object, typically loaded as native addon
|
|
51
|
-
*/
|
|
52
|
-
constructor (adapter) {
|
|
53
|
-
this._eventEmitter = new EventEmitter()
|
|
54
|
-
this._invokeId = 0
|
|
55
|
-
this._adapter = adapter
|
|
56
|
-
|
|
57
|
-
// Register callback handler
|
|
58
|
-
this._adapter.onCallback((jsonString, jsonObject) => {
|
|
59
|
-
// Only JS Adapters will provide the second argument
|
|
60
|
-
const { id, data } = jsonObject || JSON.parse(jsonString)
|
|
61
|
-
this._eventEmitter.emit(id, data)
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Creates an instance of the specified class.
|
|
67
|
-
*
|
|
68
|
-
* @param {String} className Name of the class to create an instance of
|
|
69
|
-
* @param {...Any} args Arguments to provide to the constructor
|
|
70
|
-
* @return {Object} Proxy to the created instance
|
|
71
|
-
*/
|
|
72
|
-
create (className, ...args) {
|
|
73
|
-
if (typeof className === 'string') {
|
|
74
|
-
return this._create({ className, args })
|
|
75
|
-
}
|
|
76
|
-
return this._create({
|
|
77
|
-
className: className.className,
|
|
78
|
-
instance: className.instance,
|
|
79
|
-
args: className.args
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
getInstance ({ className, instance }) {
|
|
84
|
-
const json = {
|
|
85
|
-
context: className,
|
|
86
|
-
method: '__getNamed__',
|
|
87
|
-
data: { _1: instance }
|
|
88
|
-
}
|
|
89
|
-
return this._createProxy(className, json)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
delete ({ className, instance }) {
|
|
93
|
-
let context
|
|
94
|
-
if (typeof (instance) === 'string') {
|
|
95
|
-
context = instance
|
|
96
|
-
} else if (typeof (instance) === 'object') {
|
|
97
|
-
context = instance._targetId
|
|
98
|
-
}
|
|
99
|
-
const json = {
|
|
100
|
-
context: className,
|
|
101
|
-
method: '__delete__',
|
|
102
|
-
data: { _1: context }
|
|
103
|
-
}
|
|
104
|
-
return JSON.parse(this._adapter.call(JSON.stringify(json))).data.r
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
callStatic (className, functionName, ...args) {
|
|
108
|
-
const json = {
|
|
109
|
-
context: className,
|
|
110
|
-
method: functionName,
|
|
111
|
-
data: this._packData(className, functionName, ...args)
|
|
112
|
-
}
|
|
113
|
-
return JSON.parse(this._adapter.call(JSON.stringify(json))).data.r
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Retrieves an array of all available classes (names only)
|
|
118
|
-
*
|
|
119
|
-
* @return {Array.<String>} Array of class names
|
|
120
|
-
*/
|
|
121
|
-
getAvailableClasses () {
|
|
122
|
-
return JSON.parse(this._adapter.getClasses())
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Provides the names of all currently running instances.
|
|
127
|
-
*
|
|
128
|
-
* @param {String} className Name of class to retrieve the instances for
|
|
129
|
-
* @return {Array.<String>} Array of instance names
|
|
130
|
-
*/
|
|
131
|
-
getAvailableInstances (className) {
|
|
132
|
-
return JSON.parse(this._adapter.getInstances(className))
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Provides all available member functions of the specified class.
|
|
137
|
-
*
|
|
138
|
-
* @param {String} className Name of class to provide member functions for
|
|
139
|
-
* @return {Array.<String>} Array of member function names
|
|
140
|
-
*/
|
|
141
|
-
getAvailableMemberFunctions (className) {
|
|
142
|
-
return JSON.parse(this._adapter.getMemberFunctions(className))
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Provides all available static functions of a registered class.
|
|
147
|
-
*
|
|
148
|
-
* @param {String} className Name of class to provide static functions for
|
|
149
|
-
* @return {Array.<String>} Array of static function names
|
|
150
|
-
*/
|
|
151
|
-
getAvailableStaticFunctions (className) {
|
|
152
|
-
return JSON.parse(this._adapter.getStaticFunctions(className))
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
getMetaData (className) {
|
|
156
|
-
return JSON.parse(this._adapter.getMetaData(className))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// private:
|
|
160
|
-
|
|
161
|
-
_create ({ className, instance, args = [] }) {
|
|
162
|
-
const data = instance ? { _1: instance } : {}
|
|
163
|
-
const offset = instance ? 2 : 1
|
|
164
|
-
args.forEach((value, index) => {
|
|
165
|
-
data[`_${index + offset}`] = value
|
|
166
|
-
})
|
|
167
|
-
const json = {
|
|
168
|
-
context: className,
|
|
169
|
-
method: instance ? '__createNamed__' : '__create__',
|
|
170
|
-
data
|
|
171
|
-
}
|
|
172
|
-
return this._createProxy(className, json)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
_createProxy (className, json) {
|
|
176
|
-
// Create instance
|
|
177
|
-
const ret = JSON.parse(this._adapter.call(JSON.stringify(json)))
|
|
178
|
-
const instanceId = ret.data.r
|
|
179
|
-
const proxyId = crypto.randomBytes(2).toString('hex')
|
|
180
|
-
const proxy = {
|
|
181
|
-
_targetId: instanceId,
|
|
182
|
-
_proxyId: proxyId
|
|
183
|
-
}
|
|
184
|
-
let functions = JSON.parse(this._adapter.getMemberFunctions(className))
|
|
185
|
-
// Strip off argument signature
|
|
186
|
-
functions = functions.map(name => {
|
|
187
|
-
const pos = name.indexOf('-')
|
|
188
|
-
if (pos > 0) return name.substring(0, pos)
|
|
189
|
-
else return name
|
|
190
|
-
})
|
|
191
|
-
// Remove overloads
|
|
192
|
-
const uniqueFuncs = new Set(functions)
|
|
193
|
-
// Build proxy
|
|
194
|
-
uniqueFuncs.forEach(name => {
|
|
195
|
-
proxy[name] = (...args) => {
|
|
196
|
-
const json = {
|
|
197
|
-
context: instanceId,
|
|
198
|
-
method: name,
|
|
199
|
-
data: this._packData(proxyId, name, ...args)
|
|
200
|
-
}
|
|
201
|
-
const { data } = JSON.parse(this._adapter.call(JSON.stringify(json)))
|
|
202
|
-
if (data.e) throw new Error(data.e)
|
|
203
|
-
// Handle functions returning a promise
|
|
204
|
-
if (typeof data.r === 'string' && data.r.substr(0, 5) === '__p__') {
|
|
205
|
-
return new Promise((resolve, reject) => {
|
|
206
|
-
this._eventEmitter.once(data.r, promiseData => {
|
|
207
|
-
if (promiseData.e) reject(new Error(promiseData.e))
|
|
208
|
-
else resolve(promiseData.r)
|
|
209
|
-
})
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
return data.r
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
return proxy
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
_packData (proxyId, functionName, ...args) {
|
|
219
|
-
const data = {}
|
|
220
|
-
args.forEach((value, index) => {
|
|
221
|
-
// Check whether provided argument is a function
|
|
222
|
-
if (this._isFunction(value)) {
|
|
223
|
-
const id = `__f__${proxyId}-${functionName}-${index}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`
|
|
224
|
-
data[`_${index + 1}`] = id
|
|
225
|
-
this._eventEmitter.once(id, data => {
|
|
226
|
-
const args = Object.keys(data).sort()
|
|
227
|
-
.filter(value => value[0] === '_')
|
|
228
|
-
.map(key => data[key])
|
|
229
|
-
value.apply(null, args) // This is the actual function call
|
|
230
|
-
})
|
|
231
|
-
} else if (this._isEmitter(value)) {
|
|
232
|
-
const { emitter, event } = value
|
|
233
|
-
const id = `__f__${proxyId}-${functionName}-${index}-${event}`
|
|
234
|
-
data[`_${index + 1}`] = id
|
|
235
|
-
this._eventEmitter.on(id, data => {
|
|
236
|
-
const args = Object.keys(data).sort()
|
|
237
|
-
.filter(value => value[0] === '_')
|
|
238
|
-
.map(key => data[key])
|
|
239
|
-
emitter.emit(event, ...args)
|
|
240
|
-
})
|
|
241
|
-
} else {
|
|
242
|
-
data[`_${index + 1}`] = value
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
return data
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
_isFunction (variable) {
|
|
249
|
-
const getType = {}
|
|
250
|
-
return variable && getType.toString.call(variable) === '[object Function]'
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_isEmitter (variable) {
|
|
254
|
-
return (
|
|
255
|
-
typeof variable === 'object' &&
|
|
256
|
-
variable.hasOwnProperty('emitter') &&
|
|
257
|
-
variable.hasOwnProperty('event') &&
|
|
258
|
-
typeof variable.emitter === 'object' &&
|
|
259
|
-
typeof variable.emitter.emit === 'function'
|
|
260
|
-
)
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
module.exports = VrpcLocal
|
package/vrpc/VrpcLocal.py
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Proxy(object):
|
|
6
|
-
|
|
7
|
-
def __init__(self, vrpc, caller):
|
|
8
|
-
self._vrpc = vrpc
|
|
9
|
-
self._caller = caller
|
|
10
|
-
|
|
11
|
-
def _packData(self, function, *args):
|
|
12
|
-
data = {}
|
|
13
|
-
for index, arg in enumerate(args):
|
|
14
|
-
# Argument is function
|
|
15
|
-
if (hasattr(arg, '__call__')):
|
|
16
|
-
id = self._caller.register_callback(function, index, arg)
|
|
17
|
-
data["_{}".format(index + 1)] = id
|
|
18
|
-
elif (self._isEmitter(arg)):
|
|
19
|
-
id = self._caller.register_emitter(function, index, arg)
|
|
20
|
-
data["_{}".format(index + 1)] = id
|
|
21
|
-
else:
|
|
22
|
-
data["_{}".format(index + 1)] = arg
|
|
23
|
-
return data
|
|
24
|
-
|
|
25
|
-
def _isEmitter(self, arg):
|
|
26
|
-
pass
|
|
27
|
-
return (
|
|
28
|
-
type(arg) == tuple and
|
|
29
|
-
len(arg) == 2 and
|
|
30
|
-
hasattr(arg[0], '__call__') and
|
|
31
|
-
type(arg[1] == str)
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class Caller(object):
|
|
36
|
-
|
|
37
|
-
def __init__(self, vrpc):
|
|
38
|
-
self._invoke_id = 0
|
|
39
|
-
self._callbacks = {}
|
|
40
|
-
self._emitters = {}
|
|
41
|
-
self._vrpc = vrpc
|
|
42
|
-
self._vrpc.onCallback(self._handle_callback)
|
|
43
|
-
|
|
44
|
-
def _handle_callback(self, json_string):
|
|
45
|
-
payload = json.loads(json_string)
|
|
46
|
-
id = payload['id']
|
|
47
|
-
if id in self._callbacks:
|
|
48
|
-
args = tuple(v for _, v in sorted(payload['data'].items()))
|
|
49
|
-
self._callbacks[id](*args)
|
|
50
|
-
self._callbacks.pop(id, None)
|
|
51
|
-
elif id in self._emitters:
|
|
52
|
-
emitter = self._emitters[id]
|
|
53
|
-
args = tuple(v for _, v in sorted(payload['data'].items()))
|
|
54
|
-
emitter[0](emitter[1], *args)
|
|
55
|
-
|
|
56
|
-
def register_callback(self, function, index, callback):
|
|
57
|
-
id = "__f__{}-{}-{}".format(function, index, self._invoke_id)
|
|
58
|
-
self._invoke_id = (self._invoke_id + 1) % sys.maxsize
|
|
59
|
-
if id in self._callbacks:
|
|
60
|
-
return -1
|
|
61
|
-
self._callbacks[id] = callback
|
|
62
|
-
return id
|
|
63
|
-
|
|
64
|
-
def register_emitter(self, function, index, emitter):
|
|
65
|
-
id = "__f__{}-{}".format(function, index)
|
|
66
|
-
self._emitters[id] = emitter
|
|
67
|
-
return id
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class VrpcLocal(object):
|
|
71
|
-
"""Client capable of calling functions as provided by native modules."""
|
|
72
|
-
|
|
73
|
-
def __init__(self, module=None):
|
|
74
|
-
"""Constructs an instance of a local client.
|
|
75
|
-
|
|
76
|
-
Args:
|
|
77
|
-
module (obj): A module object, typically loaded as native addon
|
|
78
|
-
|
|
79
|
-
Todo:
|
|
80
|
-
* Existing code reflects only an initial, minimal implementation
|
|
81
|
-
* Still missing: availability functions, deletion, meta data, etc.
|
|
82
|
-
* More sophisticated handling of potential threading in loaded addon
|
|
83
|
-
"""
|
|
84
|
-
self._vrpc = module
|
|
85
|
-
self._caller = Caller(self._vrpc)
|
|
86
|
-
|
|
87
|
-
def create(self, class_name, *args):
|
|
88
|
-
"""Creates an instance of the specified class.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
class_name (str): Name of the class to create an instance of
|
|
92
|
-
*args Variable number of arguments to provide to the constructor
|
|
93
|
-
|
|
94
|
-
Returns:
|
|
95
|
-
Proxy to the created instance
|
|
96
|
-
"""
|
|
97
|
-
json_string = {
|
|
98
|
-
'context': class_name,
|
|
99
|
-
'method': '__create__',
|
|
100
|
-
'data': {}
|
|
101
|
-
}
|
|
102
|
-
data = json_string['data']
|
|
103
|
-
for index, a in enumerate(args):
|
|
104
|
-
data["_{}".format(index + 1)] = a
|
|
105
|
-
|
|
106
|
-
# Create instance
|
|
107
|
-
ret = json.loads(self._vrpc.callRemote(json.dumps(json_string)))
|
|
108
|
-
instanceId = ret['data']['r']
|
|
109
|
-
functions = json.loads(
|
|
110
|
-
self._vrpc.getMemberFunctions(class_name)
|
|
111
|
-
)['functions']
|
|
112
|
-
functions = self._remove_overloads(functions)
|
|
113
|
-
proxy = {
|
|
114
|
-
# Python lambdas are broken, I can't simply make this a multi-line
|
|
115
|
-
# statement. Sorry PEP8!
|
|
116
|
-
'__init__': lambda self, vrpc, caller: Proxy.__init__(self, vrpc, caller)
|
|
117
|
-
}
|
|
118
|
-
for function in functions:
|
|
119
|
-
proxy[function] = self._make_function(instanceId, function, *args)
|
|
120
|
-
instance = type(class_name, (Proxy,), proxy)(self._vrpc, self._caller)
|
|
121
|
-
return instance
|
|
122
|
-
|
|
123
|
-
def call_static(self, class_name, function_name, *args):
|
|
124
|
-
"""Calls a static function as made available through the native addon.
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
class_name (str): Name of the static function's class
|
|
128
|
-
function_name (str): Name of the static function to be called
|
|
129
|
-
*args: Positional arguments of the static function call
|
|
130
|
-
|
|
131
|
-
Returns:
|
|
132
|
-
any: The return value of the via-proxy called function
|
|
133
|
-
|
|
134
|
-
Todo:
|
|
135
|
-
* Support callbacks
|
|
136
|
-
"""
|
|
137
|
-
json_string = {
|
|
138
|
-
'context': class_name,
|
|
139
|
-
'method': function_name,
|
|
140
|
-
'data': {}
|
|
141
|
-
}
|
|
142
|
-
data = json_string['data']
|
|
143
|
-
for index, a in enumerate(args):
|
|
144
|
-
data["_{}".format(index + 1)] = a
|
|
145
|
-
ret = json.loads(self._vrpc.callRemote(json.dumps(json_string)))
|
|
146
|
-
if (ret['data'].get('e')):
|
|
147
|
-
raise RuntimeError(ret['data']['e'])
|
|
148
|
-
return ret['data']['r']
|
|
149
|
-
|
|
150
|
-
def _remove_overloads(self, functions):
|
|
151
|
-
uniqueFunctions = set()
|
|
152
|
-
for function in functions:
|
|
153
|
-
# Strip off overload signature
|
|
154
|
-
index = function.find('-')
|
|
155
|
-
if (index > 0):
|
|
156
|
-
function = function[0:index]
|
|
157
|
-
uniqueFunctions.add(function)
|
|
158
|
-
return uniqueFunctions
|
|
159
|
-
|
|
160
|
-
def _make_function(self, instance_id, function, *args):
|
|
161
|
-
def f(self, *args):
|
|
162
|
-
json_string = {
|
|
163
|
-
'context': instance_id,
|
|
164
|
-
'method': function,
|
|
165
|
-
'data': self._packData(function, *args)
|
|
166
|
-
}
|
|
167
|
-
ret = json.loads(self._vrpc.callRemote(json.dumps(json_string)))
|
|
168
|
-
if (ret['data'].get('e')):
|
|
169
|
-
raise RuntimeError(ret['data']['e'])
|
|
170
|
-
return ret['data']['r']
|
|
171
|
-
return f
|
package/vrpc/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .VrpcLocal import VrpcLocal
|
package/vrpc/module.cpp
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
__/\\\________/\\\____/\\\\\\\\\______/\\\\\\\\\\\\\_________/\\\\\\\\\_
|
|
3
|
-
__\/\\\_______\/\\\__/\\\///////\\\___\/\\\/////////\\\____/\\\////////__
|
|
4
|
-
__\//\\\______/\\\__\/\\\_____\/\\\___\/\\\_______\/\\\__/\\\/___________
|
|
5
|
-
___\//\\\____/\\\___\/\\\\\\\\\\\/____\/\\\\\\\\\\\\\/__/\\\_____________
|
|
6
|
-
____\//\\\__/\\\____\/\\\//////\\\____\/\\\/////////___\/\\\_____________
|
|
7
|
-
_____\//\\\/\\\_____\/\\\____\//\\\___\/\\\____________\//\\\____________
|
|
8
|
-
______\//\\\\\______\/\\\_____\//\\\__\/\\\_____________\///\\\__________
|
|
9
|
-
_______\//\\\_______\/\\\______\//\\\_\/\\\_______________\////\\\\\\\\\_
|
|
10
|
-
________\///________\///________\///__\///___________________\/////////__
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Enables Python3 to run VRPC as native addon.
|
|
14
|
-
Author: Dr. Burkhard C. Heisen (https://github.com/bheisen/vrpc)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
18
|
-
Copyright (c) 2018 - 2021 Dr. Burkhard C. Heisen <burkhard.heisen@heisenware.com>.
|
|
19
|
-
|
|
20
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
22
|
-
in the Software without restriction, including without limitation the rights
|
|
23
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
25
|
-
furnished to do so, subject to the following conditions:
|
|
26
|
-
|
|
27
|
-
The above copyright notice and this permission notice shall be included in all
|
|
28
|
-
copies or substantial portions of the Software.
|
|
29
|
-
|
|
30
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
|
-
SOFTWARE.
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
#include <Python.h>
|
|
40
|
-
#include "vrpc.hpp"
|
|
41
|
-
#include "json.hpp"
|
|
42
|
-
|
|
43
|
-
#ifndef VRPC_WITH_DL
|
|
44
|
-
#include <binding.cpp>
|
|
45
|
-
#endif
|
|
46
|
-
|
|
47
|
-
namespace vrpc_python_bindings {
|
|
48
|
-
|
|
49
|
-
static PyObject* callRemote(PyObject* self, PyObject* args) {
|
|
50
|
-
const char* json_string;
|
|
51
|
-
// Check whether we got a string as single argument
|
|
52
|
-
if (!PyArg_ParseTuple(args, "s", &json_string)) {
|
|
53
|
-
PyErr_SetString(PyExc_TypeError, "Wrong argument type, expecting string");
|
|
54
|
-
return NULL;
|
|
55
|
-
}
|
|
56
|
-
std::string ret;
|
|
57
|
-
try {
|
|
58
|
-
ret = vrpc::LocalFactory::call(json_string);
|
|
59
|
-
} catch (const std::exception& e) {
|
|
60
|
-
PyErr_SetString(PyExc_RuntimeError, e.what());
|
|
61
|
-
return NULL;
|
|
62
|
-
}
|
|
63
|
-
return PyUnicode_FromString(ret.c_str());
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
static PyObject* getMemberFunctions(PyObject* self, PyObject* args) {
|
|
67
|
-
const char* class_name;
|
|
68
|
-
// Check whether we got a string as single argument
|
|
69
|
-
if (!PyArg_ParseTuple(args, "s", &class_name)) {
|
|
70
|
-
PyErr_SetString(PyExc_TypeError, "Wrong argument type, expecting string");
|
|
71
|
-
return NULL;
|
|
72
|
-
}
|
|
73
|
-
std::string ret;
|
|
74
|
-
try {
|
|
75
|
-
auto functions = vrpc::LocalFactory::get_member_functions(class_name);
|
|
76
|
-
vrpc::json j;
|
|
77
|
-
j["functions"] = functions;
|
|
78
|
-
ret = j.dump();
|
|
79
|
-
} catch (const std::exception& e) {
|
|
80
|
-
PyErr_SetString(PyExc_RuntimeError, e.what());
|
|
81
|
-
return NULL;
|
|
82
|
-
}
|
|
83
|
-
return PyUnicode_FromString(ret.c_str());
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
static PyObject* getStaticFunctions(PyObject* self, PyObject* args) {
|
|
87
|
-
const char* class_name;
|
|
88
|
-
// Check whether we got a string as single argument
|
|
89
|
-
if (!PyArg_ParseTuple(args, "s", &class_name)) {
|
|
90
|
-
PyErr_SetString(PyExc_TypeError, "Wrong argument type, expecting string");
|
|
91
|
-
return NULL;
|
|
92
|
-
}
|
|
93
|
-
std::string ret;
|
|
94
|
-
try {
|
|
95
|
-
auto functions = vrpc::LocalFactory::get_static_functions(class_name);
|
|
96
|
-
vrpc::json j;
|
|
97
|
-
j["functions"] = functions;
|
|
98
|
-
ret = j.dump();
|
|
99
|
-
} catch (const std::exception& e) {
|
|
100
|
-
PyErr_SetString(PyExc_RuntimeError, e.what());
|
|
101
|
-
return NULL;
|
|
102
|
-
}
|
|
103
|
-
return PyUnicode_FromString(ret.c_str());
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
static PyObject* callback_handler = NULL;
|
|
107
|
-
|
|
108
|
-
static void cppCallbackHandler(const vrpc::json& j) {
|
|
109
|
-
_VRPC_DEBUG << "will call back with " << j << std::endl;
|
|
110
|
-
PyObject* arglist = Py_BuildValue("(s)", j.dump().c_str());
|
|
111
|
-
PyObject* result = PyObject_CallObject(callback_handler, arglist);
|
|
112
|
-
Py_DECREF(arglist);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
static PyObject* onCallback(PyObject*, PyObject* args) {
|
|
116
|
-
PyObject* result = NULL;
|
|
117
|
-
PyObject* tmp;
|
|
118
|
-
|
|
119
|
-
if (PyArg_ParseTuple(args, "O:set_callback", &tmp)) {
|
|
120
|
-
if (!PyCallable_Check(tmp)) {
|
|
121
|
-
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
|
|
122
|
-
return NULL;
|
|
123
|
-
}
|
|
124
|
-
Py_XINCREF(tmp); // Add a reference to new callback
|
|
125
|
-
Py_XDECREF(callback_handler); // Dispose of previous callback
|
|
126
|
-
callback_handler = tmp; // Remember new callback
|
|
127
|
-
// Boilerplate to return "None"
|
|
128
|
-
Py_INCREF(Py_None);
|
|
129
|
-
result = Py_None;
|
|
130
|
-
// Register in vrpc
|
|
131
|
-
vrpc::Callback::register_callback_handler(
|
|
132
|
-
std::bind(cppCallbackHandler, std::placeholders::_1)
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Define functions in module
|
|
139
|
-
static PyMethodDef VrpcMethods[] = {
|
|
140
|
-
{
|
|
141
|
-
"callRemote",
|
|
142
|
-
callRemote,
|
|
143
|
-
METH_VARARGS,
|
|
144
|
-
"Call bound C++ function"
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
"getMemberFunctions",
|
|
148
|
-
getMemberFunctions,
|
|
149
|
-
METH_VARARGS,
|
|
150
|
-
"Lists all available member functions for requested class"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"getStaticFunctions",
|
|
154
|
-
getStaticFunctions,
|
|
155
|
-
METH_VARARGS,
|
|
156
|
-
"Lists all available static function for requested class"
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
"onCallback",
|
|
160
|
-
onCallback,
|
|
161
|
-
METH_VARARGS,
|
|
162
|
-
"Sets callback handler for all vrpc callbacks"
|
|
163
|
-
},
|
|
164
|
-
{NULL, NULL, 0, NULL} // Sentinel
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
static struct PyModuleDef vrpc_module = {
|
|
168
|
-
PyModuleDef_HEAD_INIT,
|
|
169
|
-
// name of module
|
|
170
|
-
VRPC_MODULE_NAME,
|
|
171
|
-
// module documentation, may be NULL
|
|
172
|
-
NULL,
|
|
173
|
-
// size of per-interpreter state of the module or -1 if the module keeps state in global variables
|
|
174
|
-
-1,
|
|
175
|
-
VrpcMethods
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
// Module initialization
|
|
179
|
-
PyMODINIT_FUNC \
|
|
180
|
-
VRPC_MODULE_FUNC(void) {
|
|
181
|
-
return PyModule_Create(&vrpc_module);
|
|
182
|
-
}
|
|
183
|
-
}
|