4

I have an issue with calling a C DLL function from my C# code. The C DLL has a function accepting a file name (const char *), then opens the file, performs some work on the content (reads through the FILE *) and writes the outcome to another file. I'd like to optimize it, so that the disk read/write operations are not performed, since I have the file to be processed already in a memory stream in my C# app. I have a liberty to modify both ends (C# app and C DLL). C# app is .NET 2.0 based.

I thought of extending the DLL so that it has a function that accepts and spits out a byte array, so that I could easily PInvoke it. The output part seems easy on the C side - instead from writing to a FILE * I could just save the consecutive bytes to an array - but the input seems hard. I don't know how to deal on the C side with the obtained byte array to make it into a memory stream and work on that instead on the physical file stream from this point (I don't want to rewrite the whole DLL to read from byte array instead of FILE * - I want most of the DLL internals to remain unchanged, just to wrap it and tweak ins/outs). But actually I don't know, maybe there is a better idea to do that.

So the question is: how to turn a byte array in C into a (FILE *) without writing it actually to disk and opening a FILE * to read this file? Alternatively: how to pass a memory stream from C# through PInvoke to a C DLL so that it could be easily recognized on the C side and worked with as a FILE * (again, without physical disk writes/reads, in-memory only)?

xlecoustillier
  • 16,183
  • 14
  • 60
  • 85
Aleksander
  • 238
  • 2
  • 8
  • 1
    This [question](http://stackoverflow.com/questions/539537/memory-buffer-as-file/539608) could be the same thing you ask. – RedGlow Dec 14 '12 at 08:55
  • A FILE* can only ever read/write from a physical file, the C Runtime doesn't offer an option to map it to a stream. You'll have to raise the abstraction in your C code. There's nothing in the CRT that helps you do this, but there's for example the standard COM IStream interface. Not much fun in C either, only in C++. – Hans Passant Dec 14 '12 at 09:24
  • If you have the liberty to change both, why don't you just change it all to c#? – Jodrell Dec 14 '12 at 09:26
  • 1
    @Jodrell: the DLL is quite elaborate, I don't want to rewrite it, rather to reuse it. – Aleksander Dec 14 '12 at 09:33
  • @RedGlow: thanks, part of it worked like a charm, namely using fmemopen with predefined byte array as an underlying buffer (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html) – Aleksander Dec 14 '12 at 10:33

1 Answers1

1

Named pipes in Windows are handled through memory buffers and are compatible with most file APIs. To operate a pipe use "\\.\pipe" namespace, e.g. name like "\\.\pipe\foo". To create pipe use CreateNamedPipe Win32 API. Use fopen to open it on C side.

Another alternative could be mailslot created by CreateMailSlot API and operated though "\\.\mailslot" namespace. The main difference is operating on datagrams level rather than streams as in case of pipes.

Van Jone
  • 276
  • 2
  • 7