Providing Data to a C Library API that Requires a Filename

I am developing a simple C application on Linux, aiming to utilize an existing library’s API that requires data input through a filename. The API needs a filename as a const char*, but I already have the file’s content stored in a buffer in RAM. My objective is to achieve optimal performance without creating a temporary file on disk. What are some effective methods to simulate a file-like input for this API? Here’s a basic example of my setup:

marveloustool.h:

int marveloustool_function(const char *filename);

typical_usage.cpp:

#include "marveloustool.h"
int use_function(char *filename)
{
    return marveloustool_function(filename);
}

my_program.cpp:

#include "marveloustool.h"
int my_routine() 
{
    byte* buffer = new byte[1000000];
    // Populate buffer with data
    // The buffer contains bytes equivalent to a file's content

    /* Here’s the trick: reference buffer as a filename */

    return marveloustool_function( ??? );
}

It’s important to note that the library does not support any functions for data access via a pointer, as it strictly reads from files. I considered using pipes or named FIFOs, but I’m not well-versed in their multiprocess usage. Can a named pipe be suitable when both read and written in a single process? Would this be a prudent method to employ? Otherwise, am I better off writing a temporary file? I’m eager to explore options that allow me to maximize performance without falling back to simpler methods.

Use a named FIFO (or ‘named pipe’) for this situation. It allows you to simulate files without disk I/O overhead. Here’s a streamlined way to do it:

#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include "marveloustool.h"

int my_routine() {
    // Create a named pipe
    const char *fifo_path = "/tmp/myfifo";
    mkfifo(fifo_path, 0666);

    // Open the FIFO for writing
    int fifo_fd = open(fifo_path, O_WRONLY);
    byte *buffer = new byte[1000000];
    // Populate buffer
    write(fifo_fd, buffer, /* buffer size */);
    close(fifo_fd);

    // Use the FIFO as the filename
    int result = marveloustool_function(fifo_path);

    // Clean up
    unlink(fifo_path);
    delete[] buffer;

    return result;
}

Note: Ensure the reading process opens the FIFO for reading when the writing is done. Named pipes work efficiently when handling this setup in the same process.

An alternative approach to using named pipes or temporary files could involve employing memfd_create, which is a Linux-specific system call. This call creates an anonymous file in memory (large enough to simulate conventional files without disk I/O) that can be accessed via file descriptor, and this descriptor can be referenced by a filename in your function.

Here's how you could integrate this method into your program:

#define _GNU_SOURCE
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "marveloustool.h"

int my_routine() {
    // Create an in-memory file
    int mfd = memfd_create("my_memfile", MFD_CLOEXEC);
    if (mfd == -1) {
        perror("memfd_create failed");
        return -1;
    }

    byte *buffer = new byte[1000000];
    // Populate buffer with data
    // Let's assume buffer contains bytes you need to 'write' to a file

    // Write buffer to the in-memory file
    if (write(mfd, buffer, /* buffer size */) == -1) {
        perror("write failed");
        close(mfd);
        delete[] buffer;
        return -1;
    }

    // Use lseek to return to the beginning of the file
    lseek(mfd, 0, SEEK_SET);

    // Use /proc/pid/fd/mfd as the filename
    char mfd_path[64];
    snprintf(mfd_path, sizeof(mfd_path), "/proc/%d/fd/%d", getpid(), mfd);

    int result = marveloustool_function(mfd_path);

    // Clean up
    close(mfd);
    delete[] buffer;

    return result;
}

Note: This solution provides a way to effectively manage data in memory while giving the appearance of a file, optimizing performance by avoiding disk operations. Make sure your environment supports memfd_create, as this call is not available on all Unix-like systems.