Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add jpy.byte_buffer() function #112

Merged
23 changes: 23 additions & 0 deletions src/main/c/jpy_jbyte_buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2023 JPY-CONSORTIUM Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "jpy_module.h"
#include "jpy_diag.h"
#include "jpy_jarray.h"
#include "jpy_jbyte_buffer.h"

/* This file for now is just a place-holder for future JPy_ByteBufferWrapper specific functions.
*/
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
44 changes: 44 additions & 0 deletions src/main/c/jpy_jbyte_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2023 JPY-CONSORTIUM Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef JPY_JBYTE_BUFFER_H
#define JPY_JBYTE_BUFFER_H

#ifdef __cplusplus
extern "C" {
#endif

#include "jpy_compat.h"

/**
* The Java ByteBuffer representation in Python.
*
* IMPORTANT: JPy_JByteBufferWrapper must only differ from the JPy_JObj structure by the 'pyBuffer' member
* since we use the same basic type, name JPy_JType for it. DON'T ever change member positions!
* @see JPy_JObj
*/
typedef struct JPy_JByteBufferWrapper
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
{
PyObject_HEAD
jobject objectRef;
Py_buffer *pyBuffer;
}
JPy_JByteBufferWrapper;

#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !JPY_JBYTE_BUFFER_H */
18 changes: 15 additions & 3 deletions src/main/c/jpy_jobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "jpy_module.h"
#include "jpy_diag.h"
#include "jpy_jarray.h"
#include "jpy_jbyte_buffer.h"
#include "jpy_jtype.h"
#include "jpy_jobj.h"
#include "jpy_jmethod.h"
Expand Down Expand Up @@ -181,8 +182,12 @@ void JObj_dealloc(JPy_JObj* self)
if (array->buf != NULL) {
JArray_ReleaseJavaArrayElements(array, array->javaType);
}

}
} else if (jtype == JPy_JByteBuffer) {
JPy_JByteBufferWrapper* byteBufferWrapper;
byteBufferWrapper = (JPy_JByteBufferWrapper *) self;
PyBuffer_Release(byteBufferWrapper->pyBuffer);
PyMem_Free(byteBufferWrapper->pyBuffer);
}

jenv = JPy_GetJNIEnv();
if (jenv != NULL) {
Expand Down Expand Up @@ -707,6 +712,7 @@ int JType_InitSlots(JPy_JType* type)
PyTypeObject* typeObj;
jboolean isArray;
jboolean isPrimitiveArray;
jboolean isByteBuffer;
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved

isArray = type->componentType != NULL;
isPrimitiveArray = isArray && type->componentType->isPrimitive;
Expand All @@ -727,7 +733,13 @@ int JType_InitSlots(JPy_JType* type)
//Py_SET_TYPE(type, &JType_Type);
//Py_SET_SIZE(type, sizeof (JPy_JType));

typeObj->tp_basicsize = isPrimitiveArray ? sizeof (JPy_JArray) : sizeof (JPy_JObj);
if (isPrimitiveArray) {
typeObj->tp_basicsize = sizeof(JPy_JArray);
} else if (type == JPy_JByteBuffer) {
typeObj->tp_basicsize = sizeof(JPy_JByteBufferWrapper);
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
} else {
typeObj->tp_basicsize = sizeof(JPy_JObj);
}
typeObj->tp_itemsize = 0;
typeObj->tp_base = type->superType != NULL ? JTYPE_AS_PYTYPE(type->superType) : &JType_Type;
//typeObj->tp_base = (PyTypeObject*) type->superType;
Expand Down
67 changes: 67 additions & 0 deletions src/main/c/jpy_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "jpy_jobj.h"
#include "jpy_conv.h"
#include "jpy_compat.h"
#include "jpy_jbyte_buffer.h"


#include <stdlib.h>
Expand All @@ -38,6 +39,7 @@ PyObject* JPy_destroy_jvm(PyObject* self, PyObject* args);
PyObject* JPy_get_type(PyObject* self, PyObject* args, PyObject* kwds);
PyObject* JPy_cast(PyObject* self, PyObject* args);
PyObject* JPy_array(PyObject* self, PyObject* args);
PyObject* JPy_byte_buffer(PyObject* self, PyObject* args);


static PyMethodDef JPy_Functions[] = {
Expand All @@ -63,6 +65,9 @@ static PyMethodDef JPy_Functions[] = {
"array(name, init) - Return a new Java array of given Java type (type name or type object) and initializer (array length or sequence). "
"Possible primitive types are 'boolean', 'byte', 'char', 'short', 'int', 'long', 'float', and 'double'."},

{"byte_buffer", JPy_byte_buffer, METH_VARARGS,
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
"byte_buffer(obj) - Return a new Java direct ByteBuffer referring to the Py_buffer provided by obj via its implemented Buffer Protocol. "},

{NULL, NULL, 0, NULL} /*Sentinel*/
};

Expand Down Expand Up @@ -126,6 +131,7 @@ JPy_JType* JPy_JPyObject = NULL;
JPy_JType* JPy_JPyModule = NULL;
JPy_JType* JPy_JThrowable = NULL;
JPy_JType* JPy_JStackTraceElement = NULL;
JPy_JType* JPy_JByteBuffer = NULL;


// java.lang.Comparable
Expand Down Expand Up @@ -228,6 +234,7 @@ jclass JPy_Void_JClass = NULL;
jclass JPy_String_JClass = NULL;
jclass JPy_PyObject_JClass = NULL;
jclass JPy_PyDictWrapper_JClass = NULL;
jclass JPy_ByteBuffer_JClass = NULL;

jmethodID JPy_PyObject_GetPointer_MID = NULL;
jmethodID JPy_PyObject_UnwrapProxy_SMID = NULL;
Expand Down Expand Up @@ -660,6 +667,58 @@ PyObject* JPy_array(PyObject* self, PyObject* args)
JPy_FRAME(PyObject*, NULL, JPy_array_internal(jenv, self, args), 16)
}

PyObject* JPy_byte_buffer_internal(JNIEnv* jenv, PyObject* self, PyObject* args)
{
jobject byteBufferRef;
PyObject* pyObj;
PyObject* newPyObj;
Py_buffer *pyBuffer;
JPy_JByteBufferWrapper* byteBufferWrapper;

if (!PyArg_ParseTuple(args, "O:byte_buffer", &pyObj)) {
return NULL;
}

if (PyObject_CheckBuffer(pyObj) == 0) {
PyErr_SetString(PyExc_ValueError, "byte_buffer: argument 1 must be a Python object that supports the buffer protocol");
return NULL;
}

pyBuffer = (Py_buffer *)PyMem_Malloc(sizeof(Py_buffer));
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
if (pyBuffer == NULL) {
return PyErr_NoMemory();
}

if (PyObject_GetBuffer(pyObj, pyBuffer, PyBUF_SIMPLE | PyBUF_C_CONTIGUOUS) != 0) {
PyErr_SetString(PyExc_ValueError, "byte_buffer: the Python object failed to return a contiguous buffer.");
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
PyMem_Free(pyBuffer);
return NULL;
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
}

byteBufferRef = (*jenv)->NewDirectByteBuffer(jenv, pyBuffer->buf, pyBuffer->len);
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
if (byteBufferRef == NULL) {
PyBuffer_Release(pyBuffer);
PyMem_Free(pyBuffer);
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
return PyErr_NoMemory();
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
}

newPyObj = JObj_New(jenv, byteBufferRef);
if (newPyObj == NULL) {
PyBuffer_Release(pyBuffer);
PyMem_Free(pyBuffer);
return NULL;
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved
}
byteBufferWrapper = (JPy_JByteBufferWrapper *) newPyObj;
byteBufferWrapper->pyBuffer = pyBuffer;
return (PyObject *)byteBufferWrapper;
jmao-denver marked this conversation as resolved.
Show resolved Hide resolved

}

PyObject* JPy_byte_buffer(PyObject* self, PyObject* args)
{
JPy_FRAME(PyObject*, NULL, JPy_byte_buffer_internal(jenv, self, args), 16)
}

JPy_JType* JPy_GetNonObjectJType(JNIEnv* jenv, jclass classRef)
{
jclass primClassRef;
Expand Down Expand Up @@ -927,6 +986,7 @@ int JPy_InitGlobalVars(JNIEnv* jenv)
DEFINE_CLASS(JPy_String_JClass, "java/lang/String");
DEFINE_CLASS(JPy_Throwable_JClass, "java/lang/Throwable");
DEFINE_CLASS(JPy_StackTraceElement_JClass, "java/lang/StackTraceElement");
DEFINE_CLASS(JPy_ByteBuffer_JClass, "java/nio/ByteBuffer");

// Non-Object types: Primitive types and void.
DEFINE_NON_OBJECT_TYPE(JPy_JBoolean, JPy_Boolean_JClass);
Expand All @@ -953,6 +1013,8 @@ int JPy_InitGlobalVars(JNIEnv* jenv)
DEFINE_OBJECT_TYPE(JPy_JDoubleObj, JPy_Double_JClass);
// Other objects.
DEFINE_OBJECT_TYPE(JPy_JString, JPy_String_JClass);
DEFINE_OBJECT_TYPE(JPy_JByteBuffer, JPy_ByteBuffer_JClass);

DEFINE_OBJECT_TYPE(JPy_JThrowable, JPy_Throwable_JClass);
DEFINE_OBJECT_TYPE(JPy_JStackTraceElement, JPy_StackTraceElement_JClass);
DEFINE_METHOD(JPy_Throwable_getCause_MID, JPy_Throwable_JClass, "getCause", "()Ljava/lang/Throwable;");
Expand Down Expand Up @@ -994,6 +1056,7 @@ void JPy_ClearGlobalVars(JNIEnv* jenv)
(*jenv)->DeleteGlobalRef(jenv, JPy_Number_JClass);
(*jenv)->DeleteGlobalRef(jenv, JPy_Void_JClass);
(*jenv)->DeleteGlobalRef(jenv, JPy_String_JClass);
(*jenv)->DeleteGlobalRef(jenv, JPy_ByteBuffer_JClass);
}

JPy_Comparable_JClass = NULL;
Expand All @@ -1014,6 +1077,7 @@ void JPy_ClearGlobalVars(JNIEnv* jenv)
JPy_Number_JClass = NULL;
JPy_Void_JClass = NULL;
JPy_String_JClass = NULL;
JPy_ByteBuffer_JClass = NULL;

JPy_Object_ToString_MID = NULL;
JPy_Object_HashCode_MID = NULL;
Expand Down Expand Up @@ -1061,6 +1125,8 @@ void JPy_ClearGlobalVars(JNIEnv* jenv)
JPy_XDECREF(JPy_JFloat);
JPy_XDECREF(JPy_JDouble);
JPy_XDECREF(JPy_JVoid);
JPy_XDECREF(JPy_JString);
JPy_XDECREF(JPy_JByteBuffer);
JPy_XDECREF(JPy_JBooleanObj);
JPy_XDECREF(JPy_JCharacterObj);
JPy_XDECREF(JPy_JByteObj);
Expand All @@ -1082,6 +1148,7 @@ void JPy_ClearGlobalVars(JNIEnv* jenv)
JPy_JDouble = NULL;
JPy_JVoid = NULL;
JPy_JString = NULL;
JPy_JByteBuffer = NULL;
JPy_JBooleanObj = NULL;
JPy_JCharacterObj = NULL;
JPy_JByteObj = NULL;
Expand Down
1 change: 1 addition & 0 deletions src/main/c/jpy_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ extern struct JPy_JType* JPy_JClass;
extern struct JPy_JType* JPy_JString;
extern struct JPy_JType* JPy_JPyObject;
extern struct JPy_JType* JPy_JPyModule;
extern struct JPy_JType* JPy_JByteBuffer;

// java.lang.Comparable
extern jclass JPy_Comparable_JClass;
Expand Down
Loading