Noob wants to use libexif - strategy?

Announcements and discussion for PInvoke

Moderators: Luke Jefferson, Robert

Noob wants to use libexif - strategy?

Postby HankB » Fri Mar 20, 2009 5:52 pm

Hi folks,
Noob alert - my experience with C# includes reading Petzold's free book (.NET Book Zero) and some fooling around with VC# Express Edition. (Wagner's "Effective C#" is in the queue.) I hope my question is on topic here. It seems to be a bit on the on the edge of that, so if it is not, no offense will be taken if you lock or delete this thread.

I wish to have an application examine EXIF tags in JPEG and similar files. I have found a C library - libexif - which should meet my needs. It is is open sourced and seems to be well documented. I have started a first cut of this by trying to convert the many C structs used by libexif into C# classes or structs.

The libexif library data structures consist of a number of deeply nested structs. Some of the structs include pointers to other structs as well as arrays of pointers to other structs. Overall, this seems not a very friendly API to expose to C#. I have a deeply held belief that it sould be possible to use P/Invoke to access it, but I could see spending days (hopefully not more!) getting every little bit sorted.

That may not be a bad thing, since my interest is to learn C#, though my desire is not to become an expert at P/Invoke. ;) I see three avenues to approach the problem:

1. Continue to slug it out, studying the MarshalAs options and other P/Invoke arcana until I have mastered the subject sufficiently to translate some relatively complex data structures to something usable from C#. This seems likely to be the most work, but I also learn the most.

2. Cave in and download the tool at this web site and see if it does my work for me. This could be the least work. I would only learn to the extent that I study the results that the tool produces. That also presumes the tool produces correct results and I would be in a very poor position to determine that.

3. Write a wrapper for the libexif library in C that exposes an API that is much more friendly to C#. This opens another can-O-worms in that I have to figure out how to produce a DLL using VC Express edition.

I would appreciate your thoughts on what strategy to choose. Or if you can suggest yet another approach, please do so! Please do constrain the solution to something that calls a C library from C# as that is a skill I will need for the next project I plan to work on.

I'm no stranger to programming and my most recent experience has been an embedded system written in C with previous experience including Perl, Java and C++ on Windows, Solaris, AIX, Linux and some other embedded systems.

Many thanks for your help.
hank

edit: didn't notice typo in subject!
HankB
 
Posts: 2
Joined: Fri Mar 20, 2009 5:16 pm

Postby Robert » Mon Mar 23, 2009 8:40 am

Hi Hank,

Just to clarify a little - the pinvoke.net Visual Studio add-in is just a convenient way of inserting signatures that people have posted on the pinvoke.net website already; it doesn't calculate signatures for arbitrary DLLs. (This has been requested, but I'm not sure that in most cases there's sufficient information in the DLL to allow us to do this, unfortunately.)

Assuming I've understood correctly, that leaves you with options 1) or 3). I'd probably tend towards 1), though I can't give you a good reason for saying that :).

Something that you might want to look at if you haven't seen already is the LayoutKind attribute on structs - it lets you specify automatic, sequential (with specified padding) or explicit layouts. LayoutKind.Explicit also lets you do a rather dirty hack to get something that almost looks like a C union by specifying two fields with the same Offset within the struct.

As always when working in unmanaged land, beware the 64-bit system!

Hope that helps,
Robert
Robert Chipperfield
Developer, Red Gate Software Ltd
Robert
 
Posts: 410
Joined: Mon Oct 30, 2006 11:15 am
Location: Cambridge, UK

Re:

Postby HankB » Mon Mar 23, 2009 4:19 pm

Hi Robert,
Thanks for the tips.

Robert wrote:Just to clarify a little - the pinvoke.net Visual Studio add-in is just a convenient way of inserting signatures that people have posted on the pinvoke.net website already...

Ah... No magic want to wave over the C struct and produce something that maps byte for byte to a C# struct or class. :cry: Well, actually I might have found such a tool at the REDNAEL blog. But it is more important for me to understand the details at the moment.

Assuming I've understood correctly, that leaves you with options 1) or 3). I'd probably tend towards 1), though I can't give you a good reason for saying that :).

You seem to understand correctly and the reason for me would be a deeper understanding of what's going on behind the scenes.

Something that you might want to look at if you haven't seen already is the LayoutKind attribute on structs ...

At the moment I'm going through the documentation on the Microsoft web site and studying stuff like that. So far I haven't found key parts of the picture. For example, one field of one of the structs is a char pointer. I think I can marshal it as an IntPtr, but the fact that the marshaled pointer points to a larger data type than the original makes me nervous. Another question is how to represent a 5 element array of pointers (to other structs) as a field in a C# struct/class that must be marshaled as a C struct.

As always when working in unmanaged land, beware the 64-bit system!

Indeed! I don't see a lot of commentary regarding this in the Microsoft documentation. However one example checks the size of a resulting pointer to decide whether to format it appropriately as a 32 bit vs. 64 bit pointer. Fortunately for me, I do not have access to a 64 bit Windows system on which to test. If I do go ahead and try to migrate this to a 64 bit Linux system that could be an issue.

I'm working on a slightly different approach. The first thing I did was to write a C++ application to use the library, just to make sure I understood the APIs I was using and had some confirmation that they would actually work. In doing this, I uncovered the fact that the client program does not actually need to deal with the contents of the structures. One call returns a pointer to the structure and another accepts the pointer as an argument. So this is an opaque data type - a handle - to the C# program. The program has to deal with pointers to a couple of different structs. I think can provide some type safety by wrapping the pointers in different C# structs. Managing them as int pointers would let me silently mix them up between calls and I'm sure that would result in so called undefined results in the DLL. Making the single data member within the struct a pointer type (vs. an int, which I think is SOP for Windows handle) should accommodate 64 bit systems, provided the library itself is 64 bit compliant. (And no, I'm not even going to think about using a 32 bit DLL from a 64 bit C# program :D )

I suppose the other thing that could trip me up is that some of the API is implemented as macros rather than as C calls, so those could be a bit of an issue.

thanks,
hank
HankB
 
Posts: 2
Joined: Fri Mar 20, 2009 5:16 pm


Return to PInvoke.Net

Who is online

Users browsing this forum: No registered users and 0 guests