-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcall_thread.c
150 lines (119 loc) · 3.18 KB
/
call_thread.c
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
// A sample of python embedding (calling python functions from within C code)
//
#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
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;
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 < 10; 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");
return 0;
}
void ThreadProc( void *data )
{
PyObject *pName, *pModule, *pDict, *pFunc;
PyThreadState *mainThreadState, *myThreadState, *tempState;
PyInterpreterState *mainInterpreterState;
CMD_LINE_STRUCT* arg = (CMD_LINE_STRUCT*)data;
// Initialize python inerpreter
Py_Initialize();
// Initialize thread support
PyEval_InitThreads();
// Save a pointer to the main PyThreadState object
mainThreadState = PyThreadState_Get();
// Get a reference to the PyInterpreterState
mainInterpreterState = mainThreadState->interp;
// Create a thread state object for this thread
myThreadState = PyThreadState_New(mainInterpreterState);
// Release global lock
PyEval_ReleaseLock();
// Acquire global lock
PyEval_AcquireLock();
// Swap in my thread state
tempState = PyThreadState_Swap(myThreadState);
// Now execute some python code (call python functions)
pName = PyString_FromString(arg->argv[1]);
pModule = PyImport_Import(pName);
// pDict and pFunc are borrowed references
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, arg->argv[2]);
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
}
else {
PyErr_Print();
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Swap out the current thread
PyThreadState_Swap(tempState);
// Release global lock
PyEval_ReleaseLock();
// Clean up thread state
PyThreadState_Clear(myThreadState);
PyThreadState_Delete(myThreadState);
Py_Finalize();
printf("My thread is finishing...\n");
// Exiting the thread
#ifdef WIN32
// Windows code
_endthread();
#else
// POSIX code
pthread_exit(NULL);
#endif
}