tags:

views:

246

answers:

2

Hi everyone. I gotta pass an InParameter from my C# application to an exported function from a VC++ DLL. The function accepts 2 parameters :

int func_name (FILE* fp, BYTE& by);

fp is In and by is Out parameter.

I was thinking of marshaling using IntPtr for the FILE* and using byte for BYTE. Is it correct? If I write the following in C#

[DllImport("name_of_project.dll", CharSet = CharSet.Ansi)] public static extern int func_name(IntPtr FilePointer, [MarshalAs(UnmanagedType.BYTE&)] byte by);

will it work? I think it will give an error for the '&' sign in the marshaling statement. How do I pass the out parameter by reference?

Your help would be much appreciated.

Thanks,Viren

+2  A: 

No, this won't work as written.

  1. Where are you going to get a FILE* in a C# program? Unless some other function in your unmanaged dll gives you this pointer, you're in trouble. BTW I strongly recommend wrapping this FILE* in a SafeHandle; then your p/invoke signature will use a SafeFilePointer instead of a bare IntPtr.
  2. How many bytes are you marshaling? If just one, put out byte by in the managed signature (no attributes required).
  3. You don't need to specify a charset, since you are not marshaling any chars or strings.
Anton Tykhyy
I am Marshaling 1 byte only. So can you please suggest a statement for the FILE* to be Marshalled. I am new to .NET programming and have no idea about wrapping a FILE* with SafeHandle.Thanks,Viren
VP
I'll repeat myself — where are you getting that FILE*? Do you need to open a file, or what?
Anton Tykhyy
VP
You can't do that. The `FILE*` which your unmanaged function wants belongs to the C++ runtime library linked with your unmanaged dll, which isn't necessarily the same as the C++ runtime library linked to CLR. And anyway .NET doesn't use `FILE*` internally, it builds I/O over native `HANDLE`s. Do you have control over the unmanaged dll's source?
Anton Tykhyy
I have access to it but it is a read only access. I am not allowed to modify it and it is not meant to be modified anyways as it is on a live (production) system.
VP
First of all, see whether your unmanaged dll exports file opening/closing functions. If not, and your unmanaged dll is dynamically linked to C++ runtime library, you can p/invoke `_tfopen` and `fclose` from that. You'll have to [DllImport] the same C++ runtime dll your dll uses. Otherwise you'll be reduced to hacking: essentially you'll have to re-implement `fopen` and `FILE` in managed code. But this is a very evil approach, only to be used as a *last* resort.
Anton Tykhyy
+1  A: 

If native function expects reference, you can marshal it using it ref/out. So in your situation, you could use: out byte by. I've checked it, and it works for me.

Edit again: It just came to my mind, that advices I gave you won't work, as FILE is a struct, that you won't be able to marshall from c# that easily. So scratch those, you can use this approach if you will threat SafeFileHandle as HANDLE object inside your unmanaged library. If you can't modify this dll, one solution is to create own wrapper for creating files using stdio, it could look like this:

  1. Create library that exposes functionality of fopen, fclose etc. Fe. (in c++):
    FILE* CreateFile(char* name);
  2. Marhall this function, in this example you would use (c#):
    public static extern IntPtr CreateMyFile([MarshalAs( UnmanagedType.LPStr)] string name);
  3. Marshall all FILE* parameters to IntPtr, and then just pass result of function CreateMyFile as FILE*.
Ravadre
thanks Ravadre. But I am still stuck with FILE * type marshalling. Can you please suggest a statement for the same: should I use the 4 byte unsigned integer? I do not have the code to test right now. I will get it soon and will update here asap.. For now I am thinking of the following: DllImport("name_of_project.dll", CharSet = CharSet.Ansi)]public static extern int func_name(U4 FilePointer, out byte by);
VP
Uf, sorry for all those edits, I've checked this solution and it works pretty well.
Ravadre
cool..thats a clean idea..should work without a problem i think..thanks..
VP
One point: make sure that both unmanaged dlls link to the same C++ runtime dll, or to the same version of static C++ runtime library.
Anton Tykhyy