Browse Source

Initial commit

master
Macoy Madson 6 years ago
commit
22ff4a1ed4
5 changed files with 210 additions and 0 deletions
  1. +4
    -0
      .gitignore
  2. +21
    -0
      LICENSE.txt
  3. +16
    -0
      README.md
  4. +8
    -0
      helloModule.py
  5. +161
    -0
      main.cpp

+ 4
- 0
.gitignore View File

@ -0,0 +1,4 @@
*.pyc
*.o
main
__pycache__

+ 21
- 0
LICENSE.txt View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Macoy Madson
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.

+ 16
- 0
README.md View File

@ -0,0 +1,16 @@
Python 3 Embedding and Extending with C++
==========================================
Hacked together C++ code to show how to both embed and extend Python 3 in C++ (albeit, this code is basically C because I use very few C++ features).
Note that this is basically cut-and-paste from several sources, usually not verbatim but close. See References in main.cpp to get an idea of where I got this this stuff from.
I assume you are using Linux, g++, and Python 3.4. You may have to change some stuff in order to get this running.
To Do
------
-Arguments to / from C++ functions
-Returning stuff to Python from C++
-Returning stuff from Python to C++
-Calling Python class methods
-Calling C++ class methods (probably impossible - need to wrap and use global class singletons or something)

+ 8
- 0
helloModule.py View File

@ -0,0 +1,8 @@
"""Module to test C++ embedding and extending"""
import testCAPI
def helloWorld():
print("Hello C++, it's Python!")
testCAPI.helloFromC()
return

+ 161
- 0
main.cpp View File

@ -0,0 +1,161 @@
#include <iostream>
#include <Python.h> // Note that I use -I in compile args to specify version, which isn't great
#include <string>
/* Hacked together C++ code to show how to both embed and extend
* Python 3 in C++ (albeit, this code is basically C because I use very
* few C++ features).
*
* Note that this is basically cut-and-paste from several
* sources, usually not verbatim but close. See References to get an idea of
* where I got this this stuff from
*
* --------------
* = TODO =
* --------------
*
* - Arguments to / from C++ functions
* - Returning stuff to Python from C++
* - Returning stuff from Python to C++
* - Calling Python class methods
* - Calling C++ class methods (probably impossible - need to wrap and use global class singletons or something)
* */
///////////////////////////////////////////////////////////
// Compiling + linking (assuming g++) //
///////////////////////////////////////////////////////////
/*
compile:
g++ -c -Wall -Wno-unused-result -Werror=declaration-after-statement -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -DNDEBUG -fwrapv --std=c++11 -pedantic -I/usr/include/python3.4dm "%f"
link:
g++ -o "%e" "%e.o" -L/usr/lib -lpthread -ldl -lutil -lm -lpython3.4dm -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
To get official python build/link args, use:
python3.4-config --cflags
and
python3.4-config --ldflags
*/
///////////////////////////////////////////////////////////
// References (look here when you see [n]) //
///////////////////////////////////////////////////////////
/*
https: docs.python.org/3/extending/embedding.html
(great overview for Python 3) [1]
https: docs.python.org/2/extending/embedding.html
(overview for 2.7) [2]
http: rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/
(string to pystring) [3]
https: docs.python.org/3/c-api/intro.html#embedding-python
(details about programname stuff) [4]
http: www.cplusplus.com/forum/beginner/49000/
(wchar_t conversion) [5]
http: markmail.org/message/qwex6rhhqd43jg2o
(Setting python import path (important when having private dir for python modules)) [6]
*/
///////////////////////////////////////////////////////////
// C++ API module (Python extension) //
///////////////////////////////////////////////////////////
void helloWorld(void)
{
std::cout << "Hello Python, it's C++!\n";
}
static PyObject* emb_helloWorld(PyObject* self, PyObject *args)
{
helloWorld();
return Py_BuildValue("");
}
static PyMethodDef EmbMethods[] = {
{"helloFromC", emb_helloWorld, METH_VARARGS,
"have c++ say hello"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef testCAPI = {
PyModuleDef_HEAD_INIT,
"testCAPI",
NULL,
-1,
EmbMethods
};
static PyObject* PyInit_testCAPI(void)
{
return PyModule_Create(&testCAPI);
}
///////////////////////////////////////////////////////////
// Main //
///////////////////////////////////////////////////////////
// Test python embedding and extending
// Follow [1] to get what's going on
int main()
{
PyObject *pModule;
PyObject *pModuleName;
PyObject *pModuleFunc;
// See [5]
const wchar_t c_s[] = L"/home/macoy/projects/pythonTesting/main";
wchar_t *s = new wchar_t[sizeof(c_s) / sizeof(c_s[0])];
wcscpy(s, c_s);
const wchar_t p_s[] = L":.";
wchar_t *ps = new wchar_t[sizeof(p_s) / sizeof(p_s[0])];
wcscpy(ps, p_s);
Py_SetProgramName(s); // see [4]
// Add C++ API to modules (supposed to call before Py_Initialize!). See [1]
PyImport_AppendInittab("testCAPI", &PyInit_testCAPI);
Py_Initialize();
delete[] s;
// See [6]; The below code makes it so we can import from the current directory
wchar_t *path, *newpath;
path=Py_GetPath();
newpath=new wchar_t[wcslen(path)+4];
wcscpy(newpath, path);
wcscat(newpath, ps); // ":." for unix, or ";." for windows
PySys_SetPath(newpath);
delete[] newpath;
// See [3]
pModuleName = PyUnicode_FromString("helloModule");
pModule = PyImport_Import(pModuleName);
Py_DECREF(pModuleName);
// Follow [1] to get what's going on
if (pModule != NULL)
{
pModuleFunc = PyObject_GetAttrString(pModule, "helloWorld");
if (pModuleFunc && PyCallable_Check(pModuleFunc))
{
PyObject* pArgs = NULL;
PyObject *pReturnVal = PyObject_CallObject(pModuleFunc, pArgs);
}
else
std::cout << "error: no func\n";
Py_XDECREF(pModuleFunc);
Py_DECREF(pModule);
}
else
std::cout << "error: no module\n";
// cleanup (probably missing some Py_DECREFs but oh well)
Py_Finalize();
return 0;
}

Loading…
Cancel
Save