//#include <Python.h>
//#include <stdlib.h>
//#include <stdio.h>
//#include <string.h>
//#include <errno.h>
//
//#ifdef _WIN32 // Windows includes
//#include <Windows.h>
//#include <process.h>
//#define sleep(x) Sleep(1000*x)
//HANDLE handle;
//#else // POSIX includes
//#include <pthread.h>
//pthread_t mythread;
//#endif
//
//#pragma comment(lib, "python36.lib")
//
//void ThreadProc(void*);
//
//#define NUM_ARGUMENTS 5
//typedef struct
//{
// int argc;
// char *argv[NUM_ARGUMENTS];
//} CMD_LINE_STRUCT;
//
//int main(int argc, char *argv[])
//{
// int i;
// CMD_LINE_STRUCT cmd;
// //pthread_t mythread;
//
// cmd.argc = argc;
// for (i = 0; i < NUM_ARGUMENTS; i++)
// {
// cmd.argv[i] = argv[i];
// }
//
// if (argc < 3)
// {
// fprintf(stderr,
// "Usage: call python_filename function_name [args]\n");
// return 1;
// }
//
// // Create a thread
//#ifdef _WIN32
// // Windows code
// handle = (HANDLE)_beginthread(ThreadProc, 0, &cmd);
//#else
// // POSIX code
// pthread_create(&mythread, NULL,
// ThreadProc, (void*)&cmd);
//#endif
//
// // Random testing code
// for (i = 0; i < 2; i++)
// {
// printf("Printed from the main thread.\n");
// sleep(1);
// }
//
// printf("Main Thread waiting for My Thread to complete...\n");
//
// // Join and wait for the created thread to complete...
//#ifdef _WIN32
// // Windows code
// WaitForSingleObject(handle, INFINITE);
//#else
// // POSIX code
// pthread_join(mythread, NULL);
//#endif
//
// printf("Main thread finished gracefully.\n");
//
// system("pause");
// return 0;
//}
//
//void ThreadProc(void *data)
//{
// int i;
// PyObject *pName, *pModule, *pDict,
// *pFunc, *pInstance, *pArgs, *pValue;
// PyThreadState *mainThreadState, *myThreadState, *tempState;
// PyInterpreterState *mainInterpreterState;
//
// CMD_LINE_STRUCT* arg = (CMD_LINE_STRUCT*)data;
//
// // Random testing code
// for (i = 0; i < 2; i++)
// {
// printf("...Printed from my thread.\n");
// sleep(1);
// }
//
// // Initialize python inerpreter
// Py_Initialize();
//
// // Initialize thread support
// PyEval_InitThreads();
//
// printf("%d\n", PyGILState_Check());
// // Save a pointer to the main PyThreadState object
// mainThreadState = PyThreadState_Get();
//
// printf("%d\n", PyGILState_Check());
// // Get a reference to the PyInterpreterState
// mainInterpreterState = mainThreadState->interp;
//
// printf("%d\n", PyGILState_Check());
// // Create a thread state object for this thread
// myThreadState = PyThreadState_New(mainInterpreterState);
//
// printf("%d\n", PyGILState_Check());
//
// //// Release global lock
// //PyEval_ReleaseLock();
//
// //printf("%d\n", PyGILState_Check());
// //// Acquire global lock
// //PyEval_AcquireLock();
//
// printf("%d\n", PyGILState_Check());
// // Swap in my thread state
// tempState = PyThreadState_Swap(myThreadState);
//
// printf("%d\n", PyGILState_Check());
// // Now execute some python code (call python functions)
// pName = PyUnicode_DecodeFSDefault(arg->argv[1]);
// pModule = PyImport_Import(pName);
//
// printf("%d\n", PyGILState_Check());
// // pDict and pFunc are borrowed references
// pDict = PyModule_GetDict(pModule);
// pFunc = PyDict_GetItemString(pDict, arg->argv[2]);
//
// printf("%d\n", PyGILState_Check());
// if (PyCallable_Check(pFunc))
// {
// pValue = PyObject_CallObject(pFunc, NULL);
// PyErr_Print();
// }
// else {
// PyErr_Print();
// }
//
// // Clean up
// Py_DECREF(pModule);
// Py_DECREF(pName);
//
// printf("%d\n", PyGILState_Check());
// // Swap out the current thread
// PyThreadState_Swap(tempState);
//
// printf("%d\n", PyGILState_Check());
// // Release global lock
// PyEval_ReleaseLock();
//
// printf("%d\n", PyGILState_Check());
// // Clean up thread state
// PyThreadState_Clear(myThreadState);
// PyThreadState_Delete(myThreadState);
//
// printf("%d\n", PyGILState_Check());
// Py_Finalize();
// printf("My thread is finishing...\n");
//
// // Exiting the thread
//#ifdef WIN32
// // Windows code
// _endthread();
//#else
// // POSIX code
// pthread_exit(NULL);
//#endif
//}