Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / July 2004

Tip: Looking for answers? Try searching our database.

Q: P/Invoke  with C-RunTime Library fopen() and FILE struct

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Jacek - 20 Jul 2004 17:42 GMT
Hello!

My app has to use externel dll with ANSI C interface. Some of IO functions
require passing prehistoric FILE struct as a parameter for any output input
operations.

I tried to call it with P/Invoke using following code but with no success,
the return value from fopen seems to be valid pointer, but after copying it
to FILE class String values are null and that kind of structure is treated
as null by every function utilizing it. Whats wrong with that calls?

Any ideas?

Jacek

 // FILE *fopen( const char *filename, const char *mode );
 [DllImport("msvcr71", CallingConvention=CallingConvention.Cdecl,
CharSet=CharSet.Ansi)]
 [return: MarshalAs(UnmanagedType.SysInt)]
 public static extern IntPtr fopen(
  [In, MarshalAs(UnmanagedType.LPStr)] String filename,
  [In, MarshalAs(UnmanagedType.LPStr)] String mode );

 // int fclose( FILE *stream );
 [DllImport("msvcr71", CallingConvention=CallingConvention.Cdecl,
CharSet=CharSet.Ansi)]
 [return: MarshalAs(UnmanagedType.I4)]
 public static extern int fclose( [In, MarshalAs(UnmanagedType.LPStruct)]
FILE stream );

}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class FILE
{
 [MarshalAs(UnmanagedType.LPStr)]
 public String _ptr;
 public Int16  _cnt;
 [MarshalAs(UnmanagedType.LPStr)]
 public String _base;
 public Int16  _flag;
 public Int16  _file;
 public Int16  _charbuf;
 public Int16  _bufsiz;
 [MarshalAs(UnmanagedType.LPStr)]
 public String _tmpfname;
}

IntPtr pf = Utilities.fopen(@"C:\JB.Math.test", "wt");
FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
int result = Utilities.fclose(f);
BMermuys - 20 Jul 2004 18:05 GMT
Hi,

> Hello!
>
[quoted text clipped - 8 lines]
>
> Any ideas?

Declare FILE as a struct not class, change all int16 to int. Now "FILE* xxx"
parameters, should become "ref FILE xxx".

If you don't need the FILE structure yourself, you could just use an IntPtr
as a FILE* and pass the IntPtr you got from opening the file.  Eg. :

[DllImport("msvcr71", CallingConvention=CallingConvention.Cdecl,
CharSet=CharSet.Ansi)]
public static extern int fclose( IntPtr stream );

IntPtr pf = Utilities.fopen(@"C:\JB.Math.test", "wt");
int result = Utilities.fclose(pf);

HTH,
greetings

> Jacek
>
[quoted text clipped - 34 lines]
> FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> int result = Utilities.fclose(f);
Jacek - 20 Jul 2004 20:39 GMT
> Declare FILE as a struct not class, change all int16 to int. Now "FILE* xxx"
> parameters, should become "ref FILE xxx".

Unfortunately .NET will not accept struct as return type - that kind of
P/Invoke method declaration is not supported now.
Furthermore, my understanding is that C type int is just 2 bytes in size and
corresponds to Int16 of any CLI implementation.

> If you don't need the FILE structure yourself, you could just use an IntPtr
> as a FILE* and pass the IntPtr you got from opening the file.  Eg. :

Have done it already and it works fine but only with basic C-Runtime
Functions like fputc()  fputs() etc. etc. - I can open, close read and write
but thats not what I need.

My problem is that external library makes a call to fputc() in such a way
that pointer passed to that call is treated by C-Runtime functions as a
_FILEX pointer and not FILE pointer - this leads to exception being thrown
at : EnterCriticalSection( &(((_FILEX *)pf)->lock) );
the code below comes from file.c source for msvcr71d.dll. The externale
library is on market commencing from 1991, is very extensively tested on
multiple platforms and works perfectly well with C/C++ code.

I am stuck anyway!

file.c code snippet:

void __cdecl _lock_file (
       void *pf
       )
{
       /*
        * The way the FILE (pointed to by pf) is locked depends on whether
        * it is part of _iob[] or not
        */
       if ( (pf >= (void *)_iob) && (pf <= (void
*)(&_iob[_IOB_ENTRIES-1])) )
           /*
            * FILE lies in _iob[] so the lock lies in _locktable[].
            */
           _lock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
       else
           /*
            * Not part of _iob[]. Therefore, *pf is a _FILEX and the
            * lock field of the struct is an initialized critical
            * section.
            */
           EnterCriticalSection( &(((_FILEX *)pf)->lock) );

----------->>>>>>  Exception at line 235 of original file
}

> HTH,
> greetings
[quoted text clipped - 37 lines]
> > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > int result = Utilities.fclose(f);
BMermuys - 20 Jul 2004 21:40 GMT
Hi, [Inline]

> > Declare FILE as a struct not class, change all int16 to int. Now "FILE*
> xxx"
> > parameters, should become "ref FILE xxx".
>
> Unfortunately .NET will not accept struct as return type - that kind of
> P/Invoke method declaration is not supported now.

Yes, I know.  When did I say you need to do that ?  Just use an IntPtr as
return type and if you wish to get the FILE struct, then declare it as a
struct.  You can use Marshal.PtrToStruct to get the struct.  Then use ref
FILE as parameter type for functions that need a FILE*.

> Furthermore, my understanding is that C type int is just 2 bytes in size and
> corresponds to Int16 of any CLI implementation.

It's my understanding that an int has the width of the databus, which is
4bytes on a 32 bit platform (eg. win32).

> > If you don't need the FILE structure yourself, you could just use an
> IntPtr
[quoted text clipped - 7 lines]
> that pointer passed to that call is treated by C-Runtime functions as a
> _FILEX pointer and not FILE pointer - this leads to exception being thrown

Don't know what's going on here, but it doesn't have anything to do with the
c# prototypes, pointers are untyped, so if you pass it as ref FILE or IntPtr
that's just the same, it's just an address.

It's considered a _FILEX pointer because it's not in some table, maybe two
msvcr71d.dll's are instantiated, and passing FILE* between them would cause
this problem, but I admit it's a guess.  If that's the problem then try
creating a wrapper dll that does both opening/closing files aswell as
calling your 3th party dll and call only the wrapper dll from c#.

HTH more,
greetings

> at : EnterCriticalSection( &(((_FILEX *)pf)->lock) );
> the code below comes from file.c source for msvcr71d.dll. The externale
[quoted text clipped - 72 lines]
> > > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > > int result = Utilities.fclose(f);
BMermuys - 21 Jul 2004 03:08 GMT
> Yes, I know.  When did I say you need to do that ?  Just use an IntPtr as
> return type and if you wish to get the FILE struct, then declare it as a
> struct.  You can use Marshal.PtrToStruct to get the struct.  Then use ref
> FILE as parameter type for functions that need a FILE*.

Correction:
You can marshal the pointer to struct, but you must always pass the IntPtr
you got from opening the file as an IntPtr for FILE* parameters and not as
ref FILE.

greetings

> > Furthermore, my understanding is that C type int is just 2 bytes in size
> and
[quoted text clipped - 106 lines]
> > > > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > > > int result = Utilities.fclose(f);
Jacek - 24 Jul 2004 09:41 GMT
Hello!

Thanks a lot for help - I fixed error by using newer version of external
dll - most probably it was their bug ;)

Jacek

> > Yes, I know.  When did I say you need to do that ?  Just use an IntPtr as
> > return type and if you wish to get the FILE struct, then declare it as a
[quoted text clipped - 123 lines]
> > > > > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > > > > int result = Utilities.fclose(f);
Jacek - 24 Jul 2004 10:42 GMT
Hello!

Your were right supposing that two different C Run-Time libraries were
used - one by external dll and the other by my managed dll with P/Invoke
code.
As a result pointer types and functions were mixed and working properly. New
library is linked with currently used by me msvcrt71.dll and everything is
working fine.

> It's my understanding that an int has the width of the databus, which is
> 4bytes on a 32 bit platform (eg. win32).

Not true, it would depend on compiler used i.e. gcc 3.3.3 would create 32
bit C int on x86_64 machines.

Cheers

Jacek

> Hi, [Inline]
>
[quoted text clipped - 117 lines]
> > > > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > > > int result = Utilities.fclose(f);
BMermuys - 24 Jul 2004 15:58 GMT
Hi,

> Hello!
>
[quoted text clipped - 4 lines]
> library is linked with currently used by me msvcrt71.dll and everything is
> working fine.

Glad its working now.

> > It's my understanding that an int has the width of the databus, which is
> > 4bytes on a 32 bit platform (eg. win32).
>
> Not true, it would depend on compiler used i.e. gcc 3.3.3 would create 32
> bit C int on x86_64 machines.

Right, from what I read the int should be "the most natural and fastest
datatype" on a processor but this can be vague and it is the compiler that
makes the final decission.  Don't quote me though.

Greetings

> Cheers
>
[quoted text clipped - 127 lines]
> > > > > FILE f = (FILE) Marshal.PtrToStructure(pf, typeof(FILE));
> > > > > int result = Utilities.fclose(f);

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.