Предотвращение использования временных файлов, когда функция хочет, чтобы FILE * прошел - PullRequest
3 голосов
/ 07 октября 2011

В настоящее время я использую C ++ для выполнения некоторых вычислений, связанных с графом, используя boost :: graph.boost :: graph может выводить свой граф в виде точечного файла, и я использую std :: stringstream для захвата выходного точечного файла.Таким образом, содержимое файла точек находится в памяти.

Я хочу использовать файл точек для визуализации графика (как можно быстрее).Таким образом, я хочу сгенерировать точечный файл, сгенерировать SVG-файл и распечатать его на холсте.Я хочу избегать использования временных файлов для этого, так как графики должны быть маленькими, а память все равно доступна.

Однако в Graphviz libgraph есть только функция extern Agraph_t *agread(FILE *);. Единственный способ заставить эту работу работать -взломать дескриптор файла struct __FILE, который на самом деле не переносим.

Как вы позволите библиотеке читать содержимое вашей памяти как файл в Unix / linux?

Я только что узнал, что libcgraphиз GraphViz позволяет ввести здесь перегруженную версию, но пока документация не указывает мне на какое-то полезное место.

Ответы [ 4 ]

4 голосов
/ 07 октября 2011

Ну, это, возможно, ошибка в API, но вот идея. Это предполагает, что функция agread() считывает файл как двоичные данные.

Обратите внимание, что я не знаком с используемым вами API, но я надеюсь, что в любом случае это может быть полезно.

  1. Отобразить файл в память, используя mmap().
  2. Используйте эту область памяти для построения графика.
  3. Когда приходит время для вызова agread(), откройте дескриптор этого файла в структуре FILE * (fopen() или fdopen(), если вы не закрыли дескриптор).
  4. Передайте структуру FILE *.

Редактировать: Или, игнорируйте мой ответ и используйте вызов fmemopen(). Это, вероятно, именно то, что вам нужно. Я не хотел удалять свой ответ, хотя, если кто-то в данный момент пишет ответ: -).

3 голосов
/ 07 октября 2011

Вы можете создать канал с pipe(), записать данные во входной конец и использовать fdopen(), чтобы превратить дескриптор выходного файла в дескриптор файла, подходящий для передачи в agread().

Однако, это будет работать, только если вы уверены , что данные меньше PIPE_BUF байтов ; в противном случае запись может заблокироваться навсегда, поскольку с другого конца ничего не читается.

Как правило, использование временных файлов намного проще и надежнее. Просто используйте tmpfile(), чтобы получить дескриптор файла, записать в него данные, перемотать и передать его agread():

fh = tmpfile();
fputs( data, fh );
rewind( fh );
graph = agread( fh );
fclose( fh );

(Конечно, вы должны проверить ошибки, которых я не сделал для краткости.)

1 голос
/ 13 октября 2011

Если вы хотите использовать расширение GNU libc, вы можете открыть строку C как FILE*;документация на http://www.gnu.org/s/libc/manual/html_node/String-Streams.html.

0 голосов
/ 07 октября 2011

В Windows вы можете открыть именованный канал с помощью fopen.

FILE* f = fopen("\\\\.\\Pipe\\<pipe name>", "rb");

Таким образом, вы можете создать канал в отдельном потоке, куда вы помещаете данные в него, и agread будет читать из него без необходимости во временном файле.

...