test1.cpp
#include <Python.h>
#include <iostream>
#include <vector>
#include <set>
#include <memory>
#include <map>
#include <string>
#include <fstream>
#include <sstream>
using line_no = std::vector<std::string>::size_type;
class QueryResult;
class TextQuery
{
public:
TextQuery(std::ifstream&);
~TextQuery();
QueryResult query(const std::string&) const;
private:
std::shared_ptr<std::vector<std::string>> file;
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult
{
friend std::ostream& operator<<(std::ostream&, const QueryResult&);
public:
QueryResult(std::string s,
std::shared_ptr<std::set<line_no>> p,
std::shared_ptr<std::vector<std::string>> f):
sought(s), lines(p), file(f){}
~QueryResult(){};
private:
std::string sought;
std::shared_ptr<std::set<line_no>> lines;
std::shared_ptr<std::vector<std::string>> file;
};
TextQuery::TextQuery(std::ifstream &is)
:file(new std::vector<std::string>)
{
std::string text;
while (std::getline(is, text)) {
file->push_back(text);
int n = file->size() - 1;
std::istringstream line(text);
std::string word;
while (line >> word) {
auto &lines = wm[word];
if (!lines) {
lines.reset(new std::set<line_no>);
}
lines->insert(n);
}
}
}
TextQuery::~TextQuery()
{
}
QueryResult
TextQuery::query(const std::string &sought) const
{
static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);
auto loc = wm.find(sought);
if (loc == wm.end()) {
return QueryResult(sought, nodata, file);
}
else {
return QueryResult(sought, loc->second, file);
}
}
std::ostream& operator<<(std::ostream & os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " "
<< "times" << std::endl;
for (auto num : *qr.lines) {
os << "\t(line " << num + 1 << ") "
<< *(qr.file->begin() + num) << std::endl;
}
return os;
}
void runQueries(std::ifstream &infile)
{
TextQuery tq(infile);
while (true) {
std::cout << "enter word to look for, or q to quit: ";
std::string s;
if (!(std::cin >> s) || (s == "q"))
break;
std::cout << tq.query(s) << std::endl;
}
}
// int main(int argc, char const *argv[])
// {
// std::cout << argv[0] << std::endl;
// std::cout << argv[1] << std::endl;
// std::ifstream ifs;
// ifs.open (argv[1], std::ifstream::in);
// runQueries(ifs);
// ifs.close();
// return 0;
// }
PyObject* WrappFun(PyObject* self, PyObject* args)
{
char *fileName;
if (!PyArg_ParseTuple(args, "s", &fileName))
{
std::cerr << "Parameter error!" << std::endl;
return NULL;
}
std::cout << "Search file name: " << fileName << std::endl;
std::ifstream ifs;
ifs.open(fileName, std::ifstream::in);
if (ifs.good()) {
runQueries(ifs);
}
else {
std::cerr << "file open error or no file!" << std::endl;
}
ifs.close();
return Py_BuildValue("");
}
static PyMethodDef test_methods[] = {
{"Fun", WrappFun, METH_VARARGS, "Search word in file"},
{NULL,NULL,0,NULL}
};
#if (PY_VERSION_HEX >= 0x03000000)
static struct PyModuleDef test1Module =
{
PyModuleDef_HEAD_INIT,
"test1", /* name of module */
"Module: Search word in file", /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
test_methods
};
PyMODINIT_FUNC PyInit_test1(void)
{
return PyModule_Create(&test1Module);
}
#else
extern "C"
void inittest1()
{
Py_InitModule("test1", test_methods);
}
#endif
C++的代码中已经对Python版本做了区分。
python版本是2.x使用下面命令(以python2.7为例)
g++ -std=c++11 -fPIC -shared test1.cpp -I/usr/include/python2.7 -o test1.so
python版本是3.x使用下面命令(以python3.5为例)
g++ -std=c++11 -fPIC -shared test1.cpp -I/usr/include/python3.5 -o test1.so
# -*- coding: utf-8 -*-
# !usr/bin/env python
import test1
if __name__ == '__main__':
print(test1.Fun.__doc__)
test1.Fun("test1.cpp")