I am trying to compile a custom pytorch module with functions and classes from a namespace, and this results in a dynamic library having undefined symbol. However, if i take the namespace away, the module worked. What is wrong with the codes?
My codes looks like:
// scatter.h
#include <iostream>
#include <vector>
#include <string>
#include <stdint.h>
// namespace perception
// {
struct pShape
{
static const int32_t kMaxDimSize = 8;
int32_t dim_num_ = 0;
int32_t dim_[kMaxDimSize] = {0};
int32_t type_[kMaxDimSize] = {0};
pShape() {}
inline int32_t CalculateSize() const
{
int32_t size = 1;
for (int32_t dim = 0; dim < dim_num_; dim++)
{
size *= dim_[dim];
}
return size;
}
inline pShape(std::vector<int32_t> shape_data)
{
if (shape_data.size() > kMaxDimSize)
{
std::cerr << "Shape data size must not be larger than " << kMaxDimSize << std::endl;
exit(-1);
}
else
{
dim_num_ = shape_data.size();
for (uint32_t i = 0; i < shape_data.size(); i++)
{
dim_[i] = shape_data[i];
}
}
}
std::string ToString() const
{
std::string output = "";
if (dim_num_ > 0)
{
for (int32_t i = 0; i < dim_num_ - 1; i++)
{
output += std::to_string(dim_[i]);
output += "x";
}
output += std::to_string(dim_[dim_num_ - 1]);
}
else
{
std::cerr << "Warning, Shape's dimension number is 0. " << std::endl;
}
return output;
}
bool operator==(const pShape &shape_another) const
{
if (dim_num_ == shape_another.dim_num_)
{
for (int32_t i = 0; i < dim_num_; i++)
{
if (dim_[i] != shape_another.dim_[i])
{
return false;
}
}
return true;
}
else
{
return false;
}
}
bool operator!=(const pShape &shape_another) const
{
return !(*this == shape_another);
}
};
template <typename T_D>
int32_t LaunchGatherKernel(int32_t batch_size, const T_D *input,
T_D *output, const int32_t *index,
const int32_t dim, pShape &input_shape,
pShape &output_shape, void* stream);
// }
// scatter.cu
#include "scatter.h"
// #include "utils/atomics.h" // must be included in .cu
#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_fp16.h>
const static int kThreadPerBlock=1024;
// namespace perception
// {
template <typename T_D>
__global__ void gather_kernel(const T_D *input,
T_D *output,
const int32_t *index,
int32_t output_size,
pShape input_shape,
pShape output_shape,
int32_t dim)
{
int32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
__shared__ unsigned char shapes_ptr[2 * sizeof(pShape)];
pShape *shapes = (pShape *)shapes_ptr;
if (threadIdx.x == 0)
{
shapes[0] = input_shape;
shapes[1] = output_shape;
}
__syncthreads();
if (idx >= output_size)
return;
int32_t tmp = idx;
int32_t out_idx = index[idx];
const int32_t channels = output_shape.dim_num_;
int32_t dim_index[8] = {0};
int32_t cum_prod = 1;
for (int i = channels - 1; i >= 0; --i)
{
int c_value = shapes[1].dim_[i];
cum_prod *= c_value;
int32_t index_i = tmp % c_value;
dim_index[i] = index_i;
tmp = (tmp - index_i) / c_value;
}
// this will cause diverge
if (dim == 0)
{
out_idx = out_idx * shapes[0].dim_[1] + dim_index[1];
}
else
{
out_idx = dim_index[0] * shapes[0].dim_[1] + out_idx;
}
output[idx] = input[out_idx];
}
template <typename T_D>
int32_t LaunchGatherKernel(int32_t batch_size,
const T_D *input,
T_D *output,
const int32_t *index,
const int32_t dim,
pShape &input_shape,
pShape &output_shape,
void* stream)
{
int32_t output_size = output_shape.CalculateSize();
int32_t input_size = input_shape.CalculateSize();
int32_t block_size = (output_size + kThreadPerBlock - 1) / kThreadPerBlock;
dim3 grid_dim(block_size, 1, 1);
dim3 block_dim(kThreadPerBlock, 1, 1);
// START_CUDA_PERF("gather", stream);
gather_kernel<T_D><<<grid_dim, block_dim, 0, (cudaStream_t) stream>>>(input, output, index,
output_size, input_shape, output_shape, dim);
// CUDA_CHECK_RETURN(cudaGetLastError());
// STOP_CUDA_PERF("gather");
return 0;
}
template int32_t LaunchGatherKernel<float>(int32_t batch_size,
const float *input,
float *output,
const int32_t *index,
const int32_t dim,
pShape &input_shape,
pShape &output_shape,
void* stream);
template <typename T>
__global__ void GatherSimpleKernel(T* out, T* in,
int32_t* index, int32_t lenind,
int32_t numchannel, int32_t broadcast)
{
int32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
if (broadcast == 0) // no broadcast, which means the index is (lenind * numchannel)
{
out[]
return;
}
if (broadcast == 1) // broadcast index to every channel. index is (lenind)
{
return;
}
}
template <typename T>
void GatherSimpleKernelLauncher(T* out, T* in,
int32_t* index, int32_t lenind,
int32_t numchannel, int32_t broadcast,
void* stream)
#ifdef CUDA_HALF
template int32_t LaunchGatherKernel<half>(int32_t batch_size,
const half *input,
half *output,
const int32_t *index,
const int32_t dim,
Shape &input_shape,
Shape &output_shape,
void* stream);
#endif
// }
// scatter_torch.cpp
#include <torch/extension.h>
#include <torch/serialize/tensor.h>
#include "scatter.h"
#pragma common
using std::vector;
// using namespace perception;
// *** torch cpp interface *** //
void scatter_gather(torch::Tensor output_feature, torch::Tensor input_feature,
torch::Tensor index){
float * d_input_feature= input_feature.data_ptr<float>();
float * d_output_feature= output_feature.data_ptr<float>();
int32_t * d_index= index.data_ptr<int32_t>();
// Find shape for features
int dim_input = input_feature.dim();
int dim_output = output_feature.dim();
vector<int> size_input;
vector<int> size_output;
for (int i=0;i<dim_input; i++) size_input.push_back(input_feature.size(i));
for (int i=0;i<dim_output; i++) size_output.push_back(output_feature.size(i));
pShape input_shape(size_input);
pShape output_shape(size_output);
// Run kernel
LaunchGatherKernel(1, d_input_feature,
d_output_feature, d_index,
dim_input, input_shape,
output_shape, NULL);
}
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("scatter_gather", &scatter_gather, "scatter_gather");
}
Here is my compile script:
import os
import subprocess
from setuptools import find_packages, setup
from torch.utils.cpp_extension import BuildExtension, CUDAExtension
__COMMON_PATH = os.path.dirname(os.path.dirname(
os.path.abspath(__file__))) + '/common'
def get_git_commit_number():
if not os.path.exists('.git'):
return '0000000'
cmd_out = subprocess.run(
['git', 'rev-parse', 'HEAD'], stdout=subprocess.PIPE)
git_commit_number = cmd_out.stdout.decode('utf-8')[:7]
return git_commit_number
def make_cuda_ext(name, module, sources,
include_dirs=[''], library_dirs=[''], libraries=[]):
cuda_ext = CUDAExtension(
name='%s.%s' % (module, name),
sources=[os.path.join(*module.split('.'), src) for src in sources],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
)
return cuda_ext
if __name__ == '__main__':
version = '0.1'
print("setup info: ")
source_files = ['core/scatter_torch.cpp', 'core/scatter.cu']
include_dirs = ['%s/include' % __COMMON_PATH]
library_dirs = ['/usr/lib']
# library_link = ['nppial', 'nppc', 'npps', 'nppif',
# 'nppig', 'nppicc', 'nppicom', 'nppidei', 'nppim']
# library_link = []
print("COMMON_PATH: %s" % __COMMON_PATH)
print("source_files: ", source_files)
print("include_dirs: ", include_dirs)
# print("link libraries: ", library_link)
print("Start building extension.\n")
setup(
name='scatter',
version=version,
description='scatter',
install_requires=[
'numpy',
'torch',
],
author='cwman',
author_email='qzh19950601#gmail.com',
license='Apache License 2.0',
packages=find_packages(),
cmdclass={'build_ext': BuildExtension},
ext_modules=[
make_cuda_ext(
name='scatter',
module='.',
sources=source_files,
include_dirs=include_dirs,
library_dirs=library_dirs,
# libraries=library_link
),
],
)
And if the scatter.*.so is imported, the python gives undefined symbol error when undoing the namespace comment.
Related
I'm working with Python and C++ integration, and I'm on MacOS.
When I use all of the PyObject methods they all seem to work but none of the PyModule methods seem to be working.
This is my code:
#include <iostream>
#include <cmath>
#include <vector>
#if PY_MAJOR_VERSION >= 3
#define PY3K
#endif
#ifdef __APPLE__
#include <Python/Python.h>
#else
#include <Python.h>
#endif
#define space " "
#define epoch int(1000)
using namespace std;
double hypothesis(const std::vector<double>& b_val, double x){
return b_val[0] + b_val[1] * x;
}
std::vector<double> regression(const std::vector<double>& x, const std::vector<double>& y,
int epochs, double learning_rate){
if(!epochs) epochs = epoch;
double _m = 0;
double _b = 0;
std::vector<double> _values(2);
int N = x.size();
for(int i = 0; i < epochs; i++){
_values[0] = _b, _values[1] = _m;
double dm = 0;
double db = 0;
double cost = 0;
for(int j = 0; j < N; j++){
double p = hypothesis(_values, x[j]);
cost += pow(y[j] - p, 2);
dm += (-2.0 / N) * (x[j] * (y[j] - p));
db += (-2.0 / N) * (y[j] - p);
}
cost /= N;
_m = _m - (learning_rate * dm);
_b = _b - (learning_rate * db);
if ((i + 1) % 100 == 0)
std::cout << "Epoch: " << (i + 1) << " Cost: " << cost << std::endl;
}
std::vector<double> result(2);
result[0] = _m, result[1] = _b;
return result;
}
static PyObject * fit(PyObject * self, PyObject * args){
PyObject *x;
PyObject *y;
double learning_rate;
int epochs;
int N;
if(!PyArg_ParseTuple(args, "00di0i", &x, &y, &epochs, &learning_rate, &N)){
return nullptr;
}
std::vector<double> _x(N), _y(N);
for(int i = 0; i < N; i++){
_x[i] = PyFloat_AsDouble(PyList_GetItem(x, (Py_ssize_t)i));
_y[i] = PyFloat_AsDouble(PyList_GetItem(y, (Py_ssize_t)i));
}
std::vector<double> _result = regression(_x, _y, epochs, learning_rate);
PyObject *result = PyTuple_New(2);
for(int i = 0; i < 2; i++){
PyTuple_SetItem(result, i, PyFloat_FromDouble(_result[i]));
}
return Py_BuildValue("s", result);
}
static PyMethodDef linreg_methods[] = {
{"fit", (PyCFunction)fit, METH_VARARGS, "Linear Regression"},
{nullptr}
};
static PyModuleDef linear_regression = {
PyModuleDef_HEAD_INIT,
"linear_regression"
"Linear Regression",
-1,
linreg_methods
};
PyMODINIT_FUNC PyInit_linear_regression(void){
return PyModule_Create(&linear_regression);
}
The output I get is error: unknown type name 'PyModuleDef'.
I can't seem to understand what the problem is.
You will need to make sure the included Python.h is from the Python3.x build, and that you link to the corresponding library, for example, on Linux that would be:
g++ my_module.cpp -I/usr/include/python3.8/ -lpython3.8
But on MacOS this file would be dependent on where/how you installed Python3. You should be able to use locate Python.h and find the Python3 directory.
I have the following c++ and header file, which I would like to compile in Cython:
c++ code:
\\ CA.cpp c++ code
#include "CA.h"
#include<iostream>
#include <vector>
Cell::Cell() {}
// construct cell: cell is defined with position (x,y,z coordinates) and neighborhood
Cell::Cell(int x, int y, int z) {
this->x = x;
this->y = y;
this->z = z;
std::vector<int> ngh;
}
// Return the neighbors of the cell
void Cell::neighbors( ) {
std::vector<int> a{ -1, 0, 1 };
std::vector<int> ranges(gridSize, 0);
for (int i = 0; i < ranges.size(); i++) {
ranges[i] = i;
}
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
int x_ngh = ranges[Cell::x + i];
int y_ngh = ranges[Cell::y + j];
int z_ngh = ranges[Cell::z + k];
int id_ngh = x_ngh + (y_ngh - 1) * gridSize + (z_ngh - 1) * gridSize * gridSize;
Cell:ngh.push_back(id_ngh);
}
}
}
}
and header file:
\\CA.h
#ifndef CA_H
#define CA_H
#include <vector>
const int gridSize = 400;
class Cell {
public:
int x, y, z;
std::vector<int> ngh;
Cell();
Cell(int x, int y, int z);
void neighbors();
};
#endif
In order to compile the code using cython I created CA.pxd file:
cdef extern from "CA.cpp":
pass
# Declare the class with cdef
cdef extern from "CA.h":
cdef cppclass Cell:
Cell() except +
Cell(int, int, int) except +
int x,y,z
neighbors()
and CA.pyx
# distutils: language = c++
from CA cimport *
from libcpp.vector cimport vector
cdef class PyCell:
cdef Cell c_cell
def __cinit__(self, int x, int y, int z):
self.c_cell = Cell(x,y,z)
def neighbors(self):
return self.c_cell.neighbors()
Finally, I created setup.py file:
from Cython.Build import cythonize
setup(ext_modules=cythonize("CA.pyx"))
When I run the command:
python setup.py build_ext --inplace
I get an error LINK : error LNK2001: unresolved external symbol PyInit_CA. I don't know why. Any help greatly appreciated.
I followed the tutorial on boost::python::numpy, found that numpy's ndarray and array could be shared inside C ++ code, and I found that using the Boost python example, I could call a python function in C ++ with arguments and return.
My goal is that boost python and python exchange numpy array values.
First, I tried to pass the numpy array to the python code with boost python. However, I only found a way to set the pylist to PyList_SET_ITEM by creating a pylist instead of a numpy array.
In C++
//https://docs.python.org/2.0/ext/buildValue.html
PyObject *Convert_Big_Array(long arr[], int length) {
PyObject *pylist, *item;
pylist = PyList_New(length);
if (pylist != NULL)
for (int i = 0; i < length; i++) {
item = PyLong_FromLong(arr[i]);
PyList_SET_ITEM(pylist, i, item);
}
return pylist;
}
int main() {
long arr[5] = { 4,3,2,6,10 };
// Python 3.x Version
Py_SetPythonHome(L"C:\\Users\\User\\Anaconda3");
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult;
Py_Initialize();
return 0;
}
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, (char*)"someFunction");
if (PyCallable_Check(pFunc)) {
pValue = Py_BuildValue("(O)", Convert_Big_Array(arr, 5));
PyErr_Print();
presult = PyObject_CallObject(pFunc, pValue);
PyErr_Print();
}
else {
PyErr_Print();
return 0;
}
boost::python::handle<> handle(presult);
std::cout << std::endl << "Python ndarray :" << p::extract<char const *>(p::str(handle)) << std::endl;
Py_DECREF(pValue);
Py_DECREF(pModule);
Py_DECREF(pName);
Py_Finalize();
return 0;
}
In Python
import numpy as np
def someFunction(text):
print(text)
return np.array([1,2,3])
With this code I find it very difficult to pass a very large C int array to Python. Is there a more efficient way?
First, if I can convert a C ++ array to ndarray using np :: from_data and then convert it to PyObject, I think I can pass this object itself to python.
Second, I want to convert PyObject (presult) created with PyObject_CallObject to np :: ndarray format. Now the code is just an example and the output is successful.
In other words, do you know how to convert ndarray (C ++) -> PyObject (C ++), PyObject (numpy c ++) -> ndarray (c ++)?
I got a answer, and post Here for others...
thank you.
//#include <Python.h>
#include <stdlib.h>
#include <boost/python/numpy.hpp>
#include <boost/python.hpp>
#include <iostream>
//
////#define BOOST_PYTHON_STATIC_LIB
//
using namespace boost::python;
namespace np = boost::python::numpy;
//https://stackoverflow.com/questions/10701514/how-to-return-numpy-array-from-boostpython/14232897#14232897
np::ndarray mywrapper() {
std::vector<short> v;
v.push_back(3);
v.push_back(5);
Py_intptr_t shape[1] = { v.size() };
np::ndarray result = np::zeros(1, shape, np::dtype::get_builtin<short>());
std::copy(v.begin(), v.end(), reinterpret_cast<short*>(result.get_data()));
//std::cout <<"C++ Memory Addr : " << std::dec << &result << std::endl;
return result;
}
//https://stackoverflow.com/questions/54904448/boost-python-nullptr-while-extracting-ndarray
int main() {
double t_end = 7;
long arr[5] = { 4,3,2,6,10 };
// Python 3.x Version
Py_SetPythonHome(L"C:\\Users\\YangwooKim\\Anaconda3");
//PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult;
Py_Initialize();
np::initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("arbName.py", name_space, name_space);
object MyFunc = name_space["someFunction"];
object result;
//for(int i=0; i<1000000; i++)
result = MyFunc(mywrapper());
//printf("Result is %d\n", PyLong_AsLong(presult));
//np::ndarray py_array = np::from_object(boost::python::object(handle));
//auto k = extract<np::ndarray>();
//np::ndarray k = np::from_object(object);
//np::ndarray k = p::extract<np::ndarray>(object);
//const np::ndarray& ret = k();
auto result_array = extract<numpy::ndarray>(result);
const numpy::ndarray& ret = result_array();
int input_size = ret.shape(0);
short* input_ptr = reinterpret_cast<short*>(ret.get_data());
//std::cout << std::endl
// << "Python ndarray :" << p::extract<char const *>(p::str(object)) << std::endl;
std::cout << std::endl << "Python ndarray :" << input_size << std::endl;
for (int i = 0; i < input_size; ++i)
std::cout <<" " <<*(input_ptr + i) <<std::endl;
//Py_Finalize();
//Py_Finalize();
return 0;
}
I need to merge the client and server code. I would appreciate your help in this regard. I share C server and client code in the combo Python. Error grapefruit are available in the bottom line.
C Server Code
#include <unistd.h>
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#include <string.h> // string function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <time.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "list.h"
#include "pack.h"
#define SOCK_PATH "../sockets/socketNodeServer"
#define DEBUG_FILE "./debug.txt"
#pragma pack(1)
// Structure definitions
typedef struct serialRx_s{
list* llistScatteredRx;
list* llistOrderedRx;
uint8_t scratchpad[SCRATCHPAD_SIZE];
uint8_t remaining;
uint16_t lostPackets;
uint16_t receivedPackets;
int fd;
}serialRx_t;
typedef struct serialTx_s{
list* llistTx;
uint16_t sentPackets;
int fd;
}serialTx_t;
typedef struct monitor_s{
struct serialRx_s *rx_p;
struct serialTx_s *tx_p;
FILE *fp;
}monitor_t;
#pragma pack()
// Public function prototypes
// Private function prototypes
static void *rxSerial_f(void *arg);
static void *txSerial_f(void *arg);
static void *log_f(void *arg);
static void *monitor_f(void *arg);
static int orderScattered_rxData(struct serialRx_s *rx);
static int fillupScratchpad(struct serialRx_s *rx);
static void freeNode(void *data);
static void *prep_TxGoodies(int fd);
static void *prep_RxGoodies(int fd);
static void *prep_monitoring(struct serialRx_s *rx, struct serialTx_s *tx);
static void set_blocking (int fd, int should_block);
static int set_interface_attribs (int fd, int speed, int parity);
static void *form_node_data_packet(void *buf, int len);
static int setNonBlocking(int fd);
static int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
// For details about blocking in non canonical (binary mode)
// check out http://www.tldp.org/HOWTO/html_single/Serial-HOWTO/
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
static void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf ("error %d setting term attributes", errno);
}
static void * prep_monitoring(struct serialRx_s *rx, struct serialTx_s *tx)
{
struct monitor_s *monitor_p = NULL;
monitor_p = (struct monitor_s *)malloc(sizeof(struct monitor_s));
if(NULL == monitor_p){
return NULL;
}
monitor_p->rx_p = rx;
monitor_p->tx_p = tx;
monitor_p->fp = fopen(DEBUG_FILE, "w+");
return monitor_p;
}
static void *prep_RxGoodies(int fd)
{
struct serialRx_s *rx = NULL;
rx = (struct serialRx_s *)malloc(sizeof(struct serialRx_s));
rx->llistScatteredRx = create_list();
rx->llistOrderedRx = create_list();
rx->fd = fd;
memset(rx->scratchpad, 0, sizeof(rx->scratchpad));
rx->remaining = 0;
rx->lostPackets = 0;
rx->receivedPackets = 0;
return rx;
}
static void *prep_TxGoodies(int fd)
{
struct serialTx_s *tx = NULL;
tx = (struct serialTx_s *)malloc(sizeof(struct serialTx_s));
tx->llistTx = create_list();
tx->fd = fd;
tx->sentPackets = 0;
return tx;
}
static void freeNode(void *data)
{
free( (uint8_t *)data);
}
static int fillupScratchpad(struct serialRx_s *rx)
{
int targetNodeIndex = -1;
int nodeLen = 0;
uint8_t *nodeData = NULL;
int offset = 0;
uint8_t *pointer = NULL;
targetNodeIndex = payloadLen_2_index(rx->llistScatteredRx, PACKET_SIZE - rx->remaining);
//printf("targetNodeIndex value %d\n", targetNodeIndex);
for(int i=0; i <= targetNodeIndex ; i++){
offset = rx->remaining;
pointer = (uint8_t *)front(rx->llistScatteredRx); // first byte is for length
nodeLen = pointer[0];
//nodeLen = ((uint8_t *)front(rx->llistScatteredRx))[0]; // first byte is for length
//printf("nodeLen in fillupScratchpad %d\n", nodeLen);
nodeData = (uint8_t *)front(rx->llistScatteredRx) + 1; // first byte is for length
memcpy(rx->scratchpad + offset, nodeData, nodeLen);
rx->remaining += nodeLen;
//for(int j=0; j<rx->remaining; j++)
//{
// printf("scratchpad[%d]: %X\n", j, (rx->scratchpad)[j]);
//}
remove_front(rx->llistScatteredRx, freeNode);
}
return targetNodeIndex;
}
static int orderScattered_rxData(struct serialRx_s *rx)
{
int packetBeginIndex = 0;
struct raw_node_data_s *raw = NULL;
// parse the scratchpad buffer until the last remaining byte
// note that since we have a larger buffer size than what we use
// it's safe to do this.
for(int i=0; i < (rx->remaining) ; i++)
{
// Check whether we have a suitable package
if(rx->scratchpad[i] == START_CODE &&
rx->scratchpad[i+PACKET_SIZE-1] == STOP_CODE)
{
//printf("start & stop matches\n");
raw = (struct raw_node_data_s *)malloc(sizeof(struct raw_node_data_s));
memcpy(raw, rx->scratchpad + i, sizeof(struct raw_node_data_s));
//print_raw_node_data(raw);
push_back(rx->llistOrderedRx, raw);
rx->receivedPackets++;
//TODO: Check for CRC
// clear up memory area between beginning of scratchpad and Stop_Code
memset(rx->scratchpad, 0, i+PACKET_SIZE-1);
// move remaining bytes to the beginning of scratchpad buffer
// no overlapping should occur but still, use memmove instead of memcpy
memmove(rx->scratchpad,
rx->scratchpad + i + PACKET_SIZE, // point to right after the healthy packet
rx->remaining - ( i + PACKET_SIZE)); // get remaining bytes after packet end
// update remaining bytes value
rx->remaining = rx->remaining - (i + PACKET_SIZE);
packetBeginIndex = i; // success
break;
}
}
// if no packets can be formed, check whether we are running out of
// scratchpad buffer, clear up memory if this is the case. Make sure
// to increase packet lost counter
//if( !packetBeginIndex && (rx->remaining >= 2 * PACKET_SIZE) )
if( (rx->remaining >= (3 * PACKET_SIZE)) )
{
printf("we are running out of space\n");
printf("scratchpad size: %d\n", rx->remaining);
for(int i=0; i < (rx->remaining) ; i++)
{
if(rx->scratchpad[i] == START_CODE){
// clear up the first packet area and move up the
// remaining bytes to the beginning of buffer
memset(rx->scratchpad, 0, i-1);
memmove(rx->scratchpad,
rx->scratchpad + i,
rx->remaining - i );
rx->remaining -= i;
rx->lostPackets += 1;
}
}
}
// don't care for START_CODE, clear up an area
// big enough to hold a full packet
if((rx->remaining >= 3 * PACKET_SIZE)){
printf("buffer is a complete mess, clear up stuff\n");
// buffer is a complete mess,
// clear up a whole packet
memset(rx->scratchpad, 0, PACKET_SIZE);
memmove(rx->scratchpad,
rx->scratchpad + PACKET_SIZE+1,
rx->remaining - PACKET_SIZE);
rx->remaining -= PACKET_SIZE;
rx->lostPackets += 1;
}
//for(int j=0; j<rx->remaining; j++)
//{
// printf("scratchpad after cleanup[%d]: %X\n", j, (rx->scratchpad)[j]);
//}
return packetBeginIndex;
}
static void *txSerial_f(void *arg)
{
struct serialTx_s *tx = (struct serialTx_s *)arg;
struct raw_node_data_s *txRaw = NULL;
int n = 0;
//txRaw = prep_transaction_data();
//print_raw_node_data(txRaw);
sleep(1);
while(1)
{
//n = write(tx->fd, txRaw, sizeof(txRaw));
if(size(tx->llistTx)){
txRaw = front(tx->llistTx);
n = write(tx->fd, txRaw, PACKET_SIZE);
//printf("sending %d bytes via serial \n", n);
remove_front(tx->llistTx, freeNode);
tx->sentPackets += 1;
}
sleep(1);
}
return NULL;
}
static void *form_node_data_packet(void *buf, int len)
{
struct raw_node_data_s *raw = NULL;
raw = (struct raw_node_data_s *)malloc(sizeof(struct raw_node_data_s));
if(!raw){
fprintf(stderr,"can't allocate memory for raw node\n");
return NULL;
}
memcpy(raw, buf, len);
//print_raw_node_data(raw);
return raw;
}
//TODO: Move this function to a new source file for socket operations
static int setNonBlocking(int fd)
{
int flags;
/* if O_NONBLOCK is defined, use the fcntl function */
if(-1 == (flags = fcntl(fd, F_GETFL, 0))){
flags = 0;
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
static void *monitor_f(void *arg)
{
struct monitor_s *mon = (struct monitor_s *)arg;
struct raw_node_data_s *txRaw = NULL;
uint8_t rxbuf[100];
// socket operation related variables
int fdBind, fdAccept;
int t, len, status;
struct sockaddr_un local;
struct sockaddr_un remote;
if(-1 == (fdBind = socket(AF_UNIX, SOCK_STREAM, 0)))
{
fprintf(stderr, "can't open socket: %s\n", strerror(errno));
return (void *)NULL;
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if( bind(fdBind, (struct sockaddr *)&local, len) == -1){
fprintf(stderr, "can't bind: %s\n", strerror(errno));
return (void *)NULL;
}
if(-1 == listen(fdBind, 5)){ // number of listenes can actually be less
fprintf(stderr, "can't listen: %s\n", strerror(errno));
return (void *)NULL;
}
for(;;){
socklen_t size = sizeof(remote);
int rcvdBytes = 0;
fprintf(stderr, "waiting for a connection\n");
if( -1 == (fdAccept = accept(fdBind, (struct sockaddr *)&remote, &size)) )
{
fprintf(stderr, "can't accept: %s\n", strerror(errno));
return (void *)NULL;
}
//setNonBlocking(fdAccept);
status = 1;
printf("connected\n");
do{
if( (t = recv(fdAccept, rxbuf, 100, 0)) > 0){
fprintf(stderr, "incoming bytes len from server: %d\n", t);
for(int ii=0; ii < t; ii++){
printf("incoming data[%i]:%X\n", ii, rxbuf[ii]);
}
txRaw = (struct raw_node_data_s *)form_node_data_packet(rxbuf, t);
push_back(mon->tx_p->llistTx, txRaw);
}else if(t < 0){
perror("recv"); // if nonblocking then wouldhaveblocked would come here too
}else{
fprintf(stderr, "server closed connection\n");
status = 0;
}
usleep(200);
}while(status);
sleep(2);
close(fdBind);
} // while(1), thread start
return NULL;
}
static void *log_f(void *arg)
{
struct monitor_s *log = (struct monitor_s *)arg;
struct raw_node_data_s *rxRaw = NULL;
while(1)
{
if( size(log->rx_p->llistOrderedRx)){
rxRaw = front(log->rx_p->llistOrderedRx);
printf("log thread\n");
print_raw_node_data(rxRaw);
remove_front(log->rx_p->llistOrderedRx, freeNode);
//fprintf(mon->fp, "\rSent Packets: %d", i);
fprintf(log->fp, "Sent Packets: %d\n", log->tx_p->sentPackets);
fprintf(log->fp, "Received Packets: %d\n", log->rx_p->receivedPackets);
fprintf(log->fp, "Dropped Packets: %d\n", log->rx_p->lostPackets);
fflush(log->fp);
sleep(1);
}
} // while (1)
return NULL;
}
static void *rxSerial_f(void *arg)
{
struct serialRx_s *rx = (struct serialRx_s *)arg;
int n = 0;
uint8_t buf[100] = {0};
uint8_t *dataPack = NULL;
tcflush(rx->fd, TCIFLUSH); /* Discards old data in the rx buffer */
while(1)
{
n = read(rx->fd, (uint8_t *)buf, sizeof(struct raw_node_data_s));
//for(int ii=0; ii < n; ii++){
// printf("incoming serial data[%i]:%X\n", ii, ((uint8_t *)buf)[ii]);
//}
if(n > 0){
//printf("read %d bytes\n", n);
dataPack = (uint8_t *)malloc(sizeof(uint8_t)* n);
dataPack[0] = n;
memcpy(dataPack + 1, buf, sizeof(uint8_t)*n);
push_back(rx->llistScatteredRx, dataPack);
//printf("linked list size after read: %d\n", size(rx->llistScatteredRx));
//for(int i=0; i<n; i++)
//{
// printf("read data[%d]: %X\n", i, dataPack[i+1]);
//}
dataPack = NULL;
memset(buf, 0, sizeof(buf)); // clear up
// Check whether we have enough data in the
// scratchpad to forma packet
fillupScratchpad(rx);
orderScattered_rxData(rx);
}else if(n < 0){
printf("error in read operation\n");
}else{
//printf("no data - rx\n");
}
sleep(1);
} // while(1)
return NULL;
} //void *rxSerial_f(void *arg)
// *************************************************
// *************************************************
// *************************************************
// ************** TODO *************************
// * Have thread functions in seperate files
// * Implement CRC check mechanism
// * Implement DAC switch mechanism
// * Implement for loop on writes to Serial Device
// to make sure that all data is sent on the tx line
int main(void)
{
pthread_t idThreadSerial[2]; // wr, rd
char *portname = "/dev/ttyS2";
struct serialRx_s *serialRx_p = NULL;
struct serialTx_s *serialTx_p = NULL;
struct monitor_s *monitor_p = NULL;
srand(time(NULL)); // generate seed data for random()
printf("size of raw_node_data_s structure: %ld\n", sizeof(struct raw_node_data_s));
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
set_interface_attribs (fd, B38400, 0); // set speed to 38400 bps, 8n1 (no parity)
//set_blocking (fd, 0); // set no blocking
serialTx_p = (struct serialTx_s *)prep_TxGoodies(fd);
serialRx_p = (struct serialRx_s *)prep_RxGoodies(fd);
monitor_p = (struct monitor_s *)prep_monitoring(serialRx_p, serialTx_p);
fwrite ("hello!\n", sizeof(uint8_t), 7, stdout);
sleep(1);
pthread_create(&idThreadSerial[3], NULL, log_f, (void *)monitor_p);
pthread_create(&idThreadSerial[2], NULL, monitor_f, (void *)monitor_p);
//pthread_create(&idThreadSerial[1], NULL, rxSerial_f, (void *)serialRx_p);
//pthread_create(&idThreadSerial[0], NULL, txSerial_f, (void *)serialTx_p);
pthread_join(idThreadSerial[0], NULL);
pthread_join(idThreadSerial[1], NULL);
pthread_join(idThreadSerial[2], NULL);
pthread_join(idThreadSerial[3], NULL);
fwrite("all threads returned, exiting now...\n", sizeof(uint8_t), 40, stdout);
return 0;
}
Python Client Code
# -*- coding: utf-8 -*-
import socket
import os, os.path
print "Connecting..."
if os.path.exists( "../sockets/socketNodeServer" ):
client = socket.socket( socket.AF_UNIX, socket.SOCK_DGRAM )
client.connect( "../sockets/socketNodeServer" )
print "Ready."
print "Ctrl-C to quit."
print "Sending 'DONE' shuts down the server and quits."
while True:
try:
x = raw_input( "> " )
if "" != x:
print "SEND:", x
client.send( x )
if "DONE" == x:
print "Shutting down."
break
except KeyboardInterrupt, k:
print "Shutting down."
client.close()
else:
print "Couldn't Connect!"
print "Done
"
Error
Connecting...
Traceback (most recent call last):
File "client.py", line 8, in <module>
client.connect( "../sockets/socketNodeServer" )
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 91] Protocol wrong type for socket
In your C-Code you create a stream
fdBind = socket(AF_UNIX, SOCK_STREAM, 0)
and in Python a datagram:
client = socket.socket( socket.AF_UNIX, socket.SOCK_DGRAM )
Sure, this is a wrong type for socket. Use the same STREAM or DGRAM on both sides.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
so I have this python script here, and I am trying to run it but I get a syntax error. I do not see anything wrong with the syntax. Here is the code:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define KSYM_NAME_LEN 127
struct sym_entry {
unsigned long long addr;
unsigned int len;
unsigned char *sym;
};
static struct sym_entry *table;
static unsigned int table_size, table_cnt;
static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
static int all_symbols = 0;
static char symbol_prefix_char = '\0';
int token_profit[0x10000];
/* the table that holds the result of the compression */
unsigned char best_table[256][2];
unsigned char best_table_len[256];
static void usage(void)
{
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
exit(1);
}
/*
* This ignores the intensely annoying "mapping symbols" found
* in ARM ELF files: $a, $t and $d.
*/
static inline int is_arm_mapping_symbol(const char *str)
{
return str[0] == '$' && strchr("atd", str[1])
&& (str[2] == '\0' || str[2] == '.');
}
static int read_symbol(FILE *in, struct sym_entry *s)
{
char str[500];
char *sym, stype;
int rc;
rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
if (rc != 3) {
if (rc != EOF) {
/* skip line */
fgets(str, 500, in);
}
return -1;
}
sym = str;
/* skip prefix char */
if (symbol_prefix_char && str[0] == symbol_prefix_char)
sym++;
/* Ignore most absolute/undefined (?) symbols. */
if (strcmp(sym, "_text") == 0)
_text = s->addr;
else if (strcmp(sym, "_stext") == 0)
_stext = s->addr;
else if (strcmp(sym, "_etext") == 0)
_etext = s->addr;
else if (strcmp(sym, "_sinittext") == 0)
_sinittext = s->addr;
else if (strcmp(sym, "_einittext") == 0)
_einittext = s->addr;
else if (strcmp(sym, "_sextratext") == 0)
_sextratext = s->addr;
else if (strcmp(sym, "_eextratext") == 0)
_eextratext = s->addr;
else if (toupper(stype) == 'A')
{
/* Keep these useful absolute symbols */
if (strcmp(sym, "__kernel_syscall_via_break") &&
strcmp(sym, "__kernel_syscall_via_epc") &&
strcmp(sym, "__kernel_sigtramp") &&
strcmp(sym, "__gp"))
return -1;
}
else if (toupper(stype) == 'U' ||
is_arm_mapping_symbol(sym))
return -1;
/* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
else if (str[0] == '$')
return -1;
/* include the type field in the symbol name, so that it gets
* compressed together */
s->len = strlen(str) + 1;
s->sym = malloc(s->len + 1);
if (!s->sym) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required amount of memory\n");
exit(EXIT_FAILURE);
}
strcpy((char *)s->sym + 1, str);
s->sym[0] = stype;
return 0;
}
static int symbol_valid(struct sym_entry *s)
{
/* Symbols which vary between passes. Passes 1 and 2 must have
* identical symbol lists. The kallsyms_* symbols below are only added
* after pass 1, they would be included in pass 2 when --all-symbols is
* specified so exclude them to get a stable symbol list.
*/
static char *special_symbols[] = {
"kallsyms_addresses",
"kallsyms_num_syms",
"kallsyms_names",
"kallsyms_markers",
"kallsyms_token_table",
"kallsyms_token_index",
/* Exclude linker generated symbols which vary between passes */
"_SDA_BASE_", /* ppc */
"_SDA2_BASE_", /* ppc */
NULL };
int i;
int offset = 1;
/* skip prefix char */
if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
offset++;
/* if --all-symbols is not specified, then symbols outside the text
* and inittext sections are discarded */
if (!all_symbols) {
if ((s->addr < _stext || s->addr > _etext)
&& (s->addr < _sinittext || s->addr > _einittext)
&& (s->addr < _sextratext || s->addr > _eextratext))
return 0;
/* Corner case. Discard any symbols with the same value as
* _etext _einittext or _eextratext; they can move between pass
* 1 and 2 when the kallsyms data are added. If these symbols
* move then they may get dropped in pass 2, which breaks the
* kallsyms rules.
*/
if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
(s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
(s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
return 0;
}
/* Exclude symbols which vary between passes. */
if (strstr((char *)s->sym + offset, "_compiled."))
return 0;
for (i = 0; special_symbols[i]; i++)
if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
return 0;
return 1;
}
static void read_map(FILE *in)
{
while (!feof(in)) {
if (table_cnt >= table_size) {
table_size += 10000;
table = realloc(table, sizeof(*table) * table_size);
if (!table) {
fprintf(stderr, "out of memory\n");
exit (1);
}
}
if (read_symbol(in, &table[table_cnt]) == 0)
table_cnt++;
}
}
static void output_label(char *label)
{
if (symbol_prefix_char)
printf(".globl %c%s\n", symbol_prefix_char, label);
else
printf(".globl %s\n", label);
printf("\tALGN\n");
if (symbol_prefix_char)
printf("%c%s:\n", symbol_prefix_char, label);
else
printf("%s:\n", label);
}
/* uncompress a compressed symbol. When this function is called, the best table
* might still be compressed itself, so the function needs to be recursive */
static int expand_symbol(unsigned char *data, int len, char *result)
{
int c, rlen, total=0;
while (len) {
c = *data;
/* if the table holds a single char that is the same as the one
* we are looking for, then end the search */
if (best_table[c][0]==c && best_table_len[c]==1) {
*result++ = c;
total++;
} else {
/* if not, recurse and expand */
rlen = expand_symbol(best_table[c], best_table_len[c], result);
total += rlen;
result += rlen;
}
data++;
len--;
}
*result=0;
return total;
}
static void write_src(void)
{
unsigned int i, k, off;
unsigned int best_idx[256];
unsigned int *markers;
char buf[KSYM_NAME_LEN+1];
printf("#include <asm/types.h>\n");
printf("#if BITS_PER_LONG == 64\n");
printf("#define PTR .quad\n");
printf("#define ALGN .align 8\n");
printf("#else\n");
printf("#define PTR .long\n");
printf("#define ALGN .align 4\n");
printf("#endif\n");
printf(".data\n");
/* Provide proper symbols relocatability by their '_text'
* relativeness. The symbol names cannot be used to construct
* normal symbol references as the list of symbols contains
* symbols that are declared static and are private to their
* .o files. This prevents .tmp_kallsyms.o or any other
* object from referencing them.
*/
output_label("kallsyms_addresses");
for (i = 0; i < table_cnt; i++) {
if (toupper(table[i].sym[0]) != 'A') {
printf("\tPTR\t_text + %#llx\n",
table[i].addr - _text);
} else {
printf("\tPTR\t%#llx\n", table[i].addr);
}
}
printf("\n");
output_label("kallsyms_num_syms");
printf("\tPTR\t%d\n", table_cnt);
printf("\n");
/* table of offset markers, that give the offset in the compressed stream
* every 256 symbols */
markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
if (!markers) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required memory\n");
exit(EXIT_FAILURE);
}
output_label("kallsyms_names");
off = 0;
for (i = 0; i < table_cnt; i++) {
if ((i & 0xFF) == 0)
markers[i >> 8] = off;
printf("\t.byte 0x%02x", table[i].len);
for (k = 0; k < table[i].len; k++)
printf(", 0x%02x", table[i].sym[k]);
printf("\n");
off += table[i].len + 1;
}
printf("\n");
output_label("kallsyms_markers");
for (i = 0; i < ((table_cnt + 255) >> 8); i++)
printf("\tPTR\t%d\n", markers[i]);
printf("\n");
free(markers);
output_label("kallsyms_token_table");
off = 0;
for (i = 0; i < 256; i++) {
best_idx[i] = off;
expand_symbol(best_table[i], best_table_len[i], buf);
printf("\t.asciz\t\"%s\"\n", buf);
off += strlen(buf) + 1;
}
printf("\n");
output_label("kallsyms_token_index");
for (i = 0; i < 256; i++)
printf("\t.short\t%d\n", best_idx[i]);
printf("\n");
}
/* table lookup compression functions */
/* count all the possible tokens in a symbol */
static void learn_symbol(unsigned char *symbol, int len)
{
int i;
for (i = 0; i < len - 1; i++)
token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
}
/* decrease the count for all the possible tokens in a symbol */
static void forget_symbol(unsigned char *symbol, int len)
{
int i;
for (i = 0; i < len - 1; i++)
token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
}
/* remove all the invalid symbols from the table and do the initial token count */
static void build_initial_tok_table(void)
{
unsigned int i, pos;
pos = 0;
for (i = 0; i < table_cnt; i++) {
if ( symbol_valid(&table[i]) ) {
if (pos != i)
table[pos] = table[i];
learn_symbol(table[pos].sym, table[pos].len);
pos++;
}
}
table_cnt = pos;
}
/* replace a given token in all the valid symbols. Use the sampled symbols
* to update the counts */
static void compress_symbols(unsigned char *str, int idx)
{
unsigned int i, len, size;
unsigned char *p1, *p2;
for (i = 0; i < table_cnt; i++) {
len = table[i].len;
p1 = table[i].sym;
/* find the token on the symbol */
p2 = memmem(p1, len, str, 2);
if (!p2) continue;
/* decrease the counts for this symbol's tokens */
forget_symbol(table[i].sym, len);
size = len;
do {
*p2 = idx;
p2++;
size -= (p2 - p1);
memmove(p2, p2 + 1, size);
p1 = p2;
len--;
if (size < 2) break;
/* find the token on the symbol */
p2 = memmem(p1, size, str, 2);
} while (p2);
table[i].len = len;
/* increase the counts for this symbol's new tokens */
learn_symbol(table[i].sym, len);
}
}
/* search the token with the maximum profit */
static int find_best_token(void)
{
int i, best, bestprofit;
bestprofit=-10000;
best = 0;
for (i = 0; i < 0x10000; i++) {
if (token_profit[i] > bestprofit) {
best = i;
bestprofit = token_profit[i];
}
}
return best;
}
/* this is the core of the algorithm: calculate the "best" table */
static void optimize_result(void)
{
int i, best;
/* using the '\0' symbol last allows compress_symbols to use standard
* fast string functions */
for (i = 255; i >= 0; i--) {
/* if this table slot is empty (it is not used by an actual
* original char code */
if (!best_table_len[i]) {
/* find the token with the breates profit value */
best = find_best_token();
/* place it in the "best" table */
best_table_len[i] = 2;
best_table[i][0] = best & 0xFF;
best_table[i][1] = (best >> 8) & 0xFF;
/* replace this token in all the valid symbols */
compress_symbols(best_table[i], i);
}
}
}
/* start by placing the symbols that are actually used on the table */
static void insert_real_symbols_in_table(void)
{
unsigned int i, j, c;
memset(best_table, 0, sizeof(best_table));
memset(best_table_len, 0, sizeof(best_table_len));
for (i = 0; i < table_cnt; i++) {
for (j = 0; j < table[i].len; j++) {
c = table[i].sym[j];
best_table[c][0]=c;
best_table_len[c]=1;
}
}
}
static void optimize_token_table(void)
{
build_initial_tok_table();
insert_real_symbols_in_table();
/* When valid symbol is not registered, exit to error */
if (!table_cnt) {
fprintf(stderr, "No valid symbol.\n");
exit(1);
}
optimize_result();
}
int main(int argc, char **argv)
{
if (argc >= 2) {
int i;
for (i = 1; i < argc; i++) {
if(strcmp(argv[i], "--all-symbols") == 0)
all_symbols = 1;
else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
char *p = &argv[i][16];
/* skip quote */
if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
p++;
symbol_prefix_char = *p;
} else
usage();
}
} else if (argc != 1)
usage();
read_map(stdin);
optimize_token_table();
write_src();
return 0;
}
Here is the error that I am getting:
File "joe.py", line 11
struct sym_entry {
^
SyntaxError: invalid syntax
Primary problem may be that the python code is actually C