Skip to content

Commit

Permalink
Python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
dusty-nv committed May 9, 2019
1 parent 2fb2b9d commit 9373224
Show file tree
Hide file tree
Showing 12 changed files with 369 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build/
build/
*.pyc
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,4 @@ add_subdirectory(camera/gst-camera)
add_subdirectory(camera/v4l2-console)
add_subdirectory(camera/v4l2-display)
add_subdirectory(display/gl-display-test)
add_subdirectory(python)
14 changes: 14 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

#
# This list contains the versions of Python that will be detected
# and the bindings built against (if that version is installed).
#
# If you want to support another version of Python, add it here.
#
set(PYTHON_BINDING_VERSIONS 2.7 3.6 3.7)

message("-- trying to build Python bindings for Python versions: ${PYTHON_BINDING_VERSIONS}")

foreach(PYTHON_BINDING_VERSION ${PYTHON_BINDING_VERSIONS})
add_subdirectory(bindings bindings_python_${PYTHON_BINDING_VERSION})
endforeach()
58 changes: 58 additions & 0 deletions python/bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# clear CMakeCache of Python version
unset(PYTHONINTERP_FOUND CACHE)
unset(PYTHON_EXECUTABLE CACHE)
unset(PYTHON_VERSION_STRING CACHE)
unset(PYTHON_VERSION_MAJOR CACHE)
unset(PYTHON_VERSION_MINOR CACHE)
unset(PYTHON_VERSION_PATCH CACHE)

unset(PYTHON_INCLUDE_PATH CACHE)
unset(PYTHON_INCLUDE_DIRS CACHE)
unset(PYTHON_INCLUDE_DIR CACHE)
unset(PYTHON_LIBRARY CACHE)
unset(PYTHON_LIBRARIES CACHE)
unset(PYTHON_DEBUG_LIBRARIES CACHE)
unset(PYTHON_MODULE_PREFIX CACHE)
unset(PYTHON_MODULE_EXTENSION CACHE)

unset(PYTHONLIBS_FOUND CACHE)
unset(PYTHONLIBS_VERSION_STRING CACHE)

# locate requested python version
message("-- detecting Python ${PYTHON_BINDING_VERSION}...")

find_package(PythonInterp ${PYTHON_BINDING_VERSION} QUIET)
find_package(PythonLibs ${PYTHON_BINDING_VERSION} QUIET)

if(NOT ${PYTHONLIBS_FOUND})
message("-- Python ${PYTHON_BINDING_VERSION} wasn't found")
return()
endif()

message("-- found Python version: ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} (${PYTHONLIBS_VERSION_STRING})")
message("-- found Python include: ${PYTHON_INCLUDE_DIRS}")
message("-- found Python library: ${PYTHON_LIBRARIES}")

include_directories(${PYTHON_INCLUDE_DIRS})

# build the bindings
file(GLOB pythonUtilsSources *.cpp)

cuda_add_library(jetson-utils-python-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} SHARED ${pythonUtilsSources})

target_link_libraries(jetson-utils-python-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} jetson-utils ${PYTHON_LIBRARIES})

set_target_properties(jetson-utils-python-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}
PROPERTIES
PREFIX ""
OUTPUT_NAME "jetson_utils_python"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/python/${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")

# install to /usr/pythonX.X/dist-packages
set(PYTHON_BINDING_INSTALL_DIR /usr/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages)

install(TARGETS jetson-utils-python-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} DESTINATION ${PYTHON_BINDING_INSTALL_DIR})

install(DIRECTORY ../python/Jetson DESTINATION ${PYTHON_BINDING_INSTALL_DIR})
install(DIRECTORY ../python/jetson DESTINATION ${PYTHON_BINDING_INSTALL_DIR})

60 changes: 60 additions & 0 deletions python/bindings/PyCUDA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#include "PyCUDA.h"



// Test function
PyObject* PyCUDA_Test( PyObject* self, PyObject* args )
{
//PyErr_SetString(PyExc_Exception, "PyCUDA -- invalid object instance");
//return NULL;

printf("PyCUDA -- test\n");

return Py_BuildValue("s", "test string"); //Py_RETURN_NONE;
}


//-------------------------------------------------------------------------------

static PyMethodDef pyCUDA_Functions[] =
{
{ "Test", (PyCFunction)PyCUDA_Test, METH_NOARGS, "Test function"},
{NULL} /* Sentinel */
};

// Register functions
PyMethodDef* PyCUDA_RegisterFunctions()
{
return pyCUDA_Functions;
}

// Register types
bool PyCUDA_RegisterTypes( PyObject* module )
{
if( !module )
return false;

return true;
}
36 changes: 36 additions & 0 deletions python/bindings/PyCUDA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#ifndef __PYTHON_BINDINGS_CUDA__
#define __PYTHON_BINDINGS_CUDA__

#include "PyUtils.h"


// Register functions
PyMethodDef* PyCUDA_RegisterFunctions();

// Register types
bool PyCUDA_RegisterTypes( PyObject* module );


#endif
151 changes: 151 additions & 0 deletions python/bindings/PyUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#include "PyUtils.h"
#include "PyCUDA.h"



const uint32_t pyUtilsMaxFunctions = 128;
uint32_t pyUtilsNumFunctions = 0;

static PyMethodDef pyUtilsFunctions[pyUtilsMaxFunctions];


// add functions
void PyUtils_AddFunctions( PyMethodDef* functions )
{
uint32_t count = 0;

if( !functions )
return;

while(true)
{
if( !functions[count].ml_name || !functions[count].ml_meth )
break;

if( pyUtilsNumFunctions >= pyUtilsMaxFunctions - 1 )
{
printf("jetson.utils -- exceeded max number of functions to register (%u)\n", pyUtilsMaxFunctions);
return;
}

memcpy(pyUtilsFunctions + pyUtilsNumFunctions, functions + count, sizeof(PyMethodDef));

pyUtilsNumFunctions++;
count++;
}
}


// register functions
bool PyUtils_RegisterFunctions()
{
printf("jetson.utils -- registering module functions...\n");

// zero the master list of functions, so it end with NULL sentinel
memset(pyUtilsFunctions, 0, sizeof(PyMethodDef) * pyUtilsMaxFunctions);

// add functions to the master list
PyUtils_AddFunctions(PyCUDA_RegisterFunctions());

printf("jetson.utils -- done registering module functions\n");
return true;
}


// register object types
bool PyUtils_RegisterTypes( PyObject* module )
{
printf("jetson.utils -- registering module types...\n");

if( !PyCUDA_RegisterTypes(module) )
printf("jetson.utils -- failed to register CUDA types\n");

printf("jetson.utils -- done registering module types\n");
return true;
}

#ifdef PYTHON_3
static struct PyModuleDef pyUtilsModuleDef = {
PyModuleDef_HEAD_INIT,
"jetson_utils_python",
NULL,
-1,
pyUtilsFunctions
};

PyMODINIT_FUNC
PyInit_jetson_utils_python(void)
{
printf("jetson.utils -- initializing Python %i.%i bindings...\n", PY_MAJOR_VERSION, PY_MINOR_VERSION);

// register functions
if( !PyUtils_RegisterFunctions() )
printf("jetson.utils -- failed to register module functions\n");

// create the module
PyObject* module = PyModule_Create(&pyUtilsModuleDef);

if( !module )
{
printf("jetson.utils -- PyModule_Create() failed\n");
return NULL;
}

// register types
if( !PyUtils_RegisterTypes(module) )
printf("jetson.utils -- failed to register module types\n");

printf("jetson.utils -- done Python %i.%i binding initialization\n", PY_MAJOR_VERSION, PY_MINOR_VERSION);
return module;
}

#else
PyMODINIT_FUNC
initjetson_utils_python(void)
{
printf("jetson.utils -- initializing Python %i.%i bindings...\n", PY_MAJOR_VERSION, PY_MINOR_VERSION);

// register functions
if( !PyUtils_RegisterFunctions() )
printf("jetson.utils -- failed to register module functions\n");

// create the module
PyObject* module = Py_InitModule("jetson_utils_python", pyUtilsFunctions);

if( !module )
{
printf("jetson.utils -- Py_InitModule() failed\n");
return;
}

// register types
if( !PyUtils_RegisterTypes(module) )
printf("jetson.utils -- failed to register module types\n");

printf("jetson.utils -- done Python %i.%i binding initialization\n", PY_MAJOR_VERSION, PY_MINOR_VERSION);
}
#endif


35 changes: 35 additions & 0 deletions python/bindings/PyUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#ifndef __PYTHON_BINDINGS_UTILS__
#define __PYTHON_BINDINGS_UTILS__

#include <Python.h>

// check Python version
#if PY_MAJOR_VERSION >= 3
#define PYTHON_3
#elif PY_MAJOR_VERSION >= 2
#define PYTHON_2
#endif

#endif
6 changes: 6 additions & 0 deletions python/python/Jetson/Utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

print("Jetson.Utils.__init__.py")

from jetson_utils_python import *

VERSION = '1.0.0'
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions python/python/jetson/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

print("jetson.utils.__init__.py")

from jetson_utils_python import *

VERSION = '1.0.0'

0 comments on commit 9373224

Please sign in to comment.