-
Notifications
You must be signed in to change notification settings - Fork 0
/
FrameworkTypes.cpp
150 lines (126 loc) · 4.88 KB
/
FrameworkTypes.cpp
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
// Copyright (c) 2019 Nicholas Corgan
// SPDX-License-Identifier: BSL-1.0
#include "JavaProxy.hpp"
#include <Pothos/Exception.hpp>
#include <Pothos/Plugin.hpp>
#include <Pothos/Proxy.hpp>
#include <Pothos/Framework/BufferChunk.hpp>
#include <Pothos/Framework/SharedBuffer.hpp>
#include <Poco/String.h>
#include <jni.h>
#include <algorithm>
#include <complex>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
static Pothos::Proxy convertBufferChunkToJavaByteBuffer(
Pothos::ProxyEnvironment::Sptr env,
const Pothos::BufferChunk& buffer)
{
auto javaProxyEnvironment = std::dynamic_pointer_cast<JavaProxyEnvironment>(env);
jobject jniByteBuffer = javaProxyEnvironment->env->NewDirectByteBuffer(
reinterpret_cast<void*>(buffer.address),
static_cast<jlong>(buffer.length));
auto bufferProxy = javaProxyEnvironment->makeHandle(jniByteBuffer);
// Cast the return buffer type to the correct subclass based on the
// BufferChunk's dtype.
static const std::unordered_map<std::string, std::string> dtypeToJavaFunc =
{
{"int8", "asCharBuffer"},
{"int16", "asShortBuffer"},
{"int32", "asIntBuffer"},
{"int64", "asLongBuffer"},
{"float32", "asFloatBuffer"},
{"float64", "asDoubleBuffer"}
};
auto mapIter = dtypeToJavaFunc.find(buffer.dtype.name());
if(mapIter != dtypeToJavaFunc.end())
{
const std::string& castFunc = mapIter->second;
bufferProxy = bufferProxy.call(castFunc);
}
else
{
throw Pothos::InvalidArgumentException("Invalid or unsupported DType: "+buffer.dtype.name());
}
return bufferProxy;
}
static bool isJavaProxySubclass(
const Pothos::Proxy& proxy,
const std::string& destClass)
{
auto env = proxy.getEnvironment();
auto proxyJavaClass = proxy.call("class");
auto destJavaClass = env->findProxy(destClass);
return destJavaClass.call<bool>("isAssignableFrom", proxyJavaClass);
}
static Pothos::BufferChunk convertJavaByteBufferToBufferChunk(const Pothos::Proxy& byteBuffer)
{
// The given byte buffer must be direct (meaning it has a "backing" array
// that can be accessed by native code).
if(!byteBuffer.call<bool>("isDirect"))
{
throw Pothos::InvalidArgumentException("The given "+byteBuffer.getClassName()+" cannot be accessed by native code.");
}
auto javaProxyEnvironment = std::dynamic_pointer_cast<JavaProxyEnvironment>(
byteBuffer.getEnvironment());
jobject jniByteBuffer = javaProxyEnvironment->getHandle(byteBuffer)->toJobject();
void* address = javaProxyEnvironment->env->GetDirectBufferAddress(jniByteBuffer);
jlong capacity = javaProxyEnvironment->env->GetDirectBufferCapacity(jniByteBuffer);
static const std::unordered_map<std::string, std::string> javaClassToDType =
{
{"java.nio.ByteBuffer", "int8"},
{"java.nio.CharBuffer", "int8"},
{"java.nio.ShortBuffer", "int16"},
{"java.nio.IntBuffer", "int32"},
{"java.nio.LongBuffer", "int64"},
{"java.nio.FloatBuffer", "float32"},
{"java.nio.DoubleBuffer", "float64"},
};
using MapPair = std::unordered_map<std::string, std::string>::value_type;
auto applicableClassIter = std::find_if(
javaClassToDType.begin(),
javaClassToDType.end(),
[&byteBuffer](const MapPair& mapPair)
{
return isJavaProxySubclass(byteBuffer, mapPair.first);
});
if(applicableClassIter == javaClassToDType.end())
{
throw Pothos::InvalidArgumentException("Could not find valid DType for "+byteBuffer.getClassName());
}
Pothos::DType dtype(applicableClassIter->second);
auto sharedBuff = Pothos::SharedBuffer(
reinterpret_cast<size_t>(address),
static_cast<size_t>(capacity * dtype.elemSize()),
byteBuffer.getHandle());
auto chunk = Pothos::BufferChunk(sharedBuff);
chunk.dtype = dtype;
return chunk;
}
pothos_static_block(pothosRegisterJavaByteBufferConversions)
{
Pothos::PluginRegistry::addCall(
"/proxy/converters/java/bufferchunk_to_java_bytebuffer",
&convertBufferChunkToJavaByteBuffer);
const std::vector<std::string> compatibleByteBufferClasses =
{
"ByteBuffer",
"CharBuffer",
"ShortBuffer",
"IntBuffer",
"LongBuffer",
"FloatBuffer",
"DoubleBuffer"
};
for(const std::string& byteBufferClass: compatibleByteBufferClasses)
{
const std::string lowerName = Poco::toLower(byteBufferClass);
Pothos::PluginRegistry::add(
"/proxy/converters/java/java_"+lowerName+"_to_bufferchunk",
Pothos::ProxyConvertPair(
"java.nio."+byteBufferClass,
&convertJavaByteBufferToBufferChunk));
}
}