Project

General

Profile

Newbie writing a C wrapper for Exiv2

Added by Clive McCarthy about 3 years ago

I'm not a C++ programmer so I'm writing a small wrapper to interface Exiv2 to my C code. It's is very simple but I just can't figure out the necessary methods to get the C++ data into my C data structures. It really is my ignorance of C++ but I'd appreciate some help! My wrapper looks like the following. You can see the erroneous lines near the end.


Replies (3)

RE: Newbie writing a C wrapper for Exiv2 - Added by Robin Mills about 3 years ago

You are going in the correct direction.

Here's what I would do with my favourite test file (which is only my web-site)

832 rmills@rmillsmbp:~/gnu/github/exiv2/exiv2/build $ bin/exiv2 -pa --grep date/i  http://clanmills.com/Stonehenge.jpg
Exif.Image.DateTime                          Ascii      20  2015:07:16 20:25:28
Exif.Photo.DateTimeOriginal                  Ascii      20  2015:07:16 15:38:54
Exif.Photo.DateTimeDigitized                 Ascii      20  2015:07:16 15:38:54
Exif.NikonWt.DateDisplayFormat               Byte        1  Y/M/D
Exif.GPSInfo.GPSDateStamp                    Ascii      11  2015:07:16
Xmp.xmp.ModifyDate                           XmpText    25  2015-07-16T20:25:28+01:00
There's a sample program exifvalue that prints the value of an Exif tag:
833 rmills@rmillsmbp:~/gnu/github/exiv2/exiv2/build $ bin/exifvalue http://clanmills.com/Stonehenge.jpg Exif.Photo.DateTimeOriginal
2015:07:16 15:38:54
834 rmills@rmillsmbp:~/gnu/github/exiv2/exiv2/build $
Let's write exifvalue in "C".
1) put main in main.c.
2) put the C++ magic in wrapper.cpp
3) the header file into wrapper.h

main.c

// ***************************************************************** -*- C -*-
// main.c (samples/exifvalue.cpp written in C)

#include "wrapper.h" 
#include <stdio.h>

// To build:
// g++ -std=c++98 main.c wrapper.cpp -I/usr/local/include -L/usr/local/lib -lexiv2 -o main
//
// To test:
// ./main http://clanmills.com/Stonehenge.jpg Exif.Photo.DateTimeOriginal
// 2015:07:16 15:38:54
//
int main(int argc, const char* argv[])
{
    const char* prog = argv[0];
    const char* path = argv[1];
    const char* key  = argv[2];
    int         rc   = 0      ;

    if (argc != 3) {
        printf("Usage: %s path key\n",prog);
        rc = 1;
    } else {
       char buffer[100];
       if ( getMetadata(path,key,buffer,sizeof(buffer)) ) {
           printf("%s\n",buffer);
       } else {
           printf("key %s not in %s\n",key,path);
           rc = 2;
       }
    }
    return rc;
}

wrapper.h

#ifdef __cplusplus
extern "C" {
#endif

int getMetadata(const char* path,const char* key,char* buffer,const int buffer_l);

#ifdef __cplusplus
}
#endif

wrapper.cpp

// ***************************************************************** -*- C++ -*-
// wrapper.cpp

#include <exiv2/exiv2.hpp>
#include "wrapper.h" 

extern "C" 
{
    int getMetadata(const char* path,const char* key,char* buffer,int buffer_l) {
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
        assert(image.get() != 0);
        image->readMetadata();
        Exiv2::ExifData& exifData = image->exifData();
        strcpy(buffer,   exifData[key].toString().c_str());
        return 1;
    }
}

This was quickly written. I have not put exception handling and buffer overflow checks in wrapper.cpp

I'm really busy at the moment working on Exiv2 v0.27 RC1. If you want to discuss this in more detail, can I ask you to wait until next week. I will be happy to screen share with you if you need some one-to-one assistance.

RE: Newbie writing a C wrapper for Exiv2 [solved] - Added by Clive McCarthy about 3 years ago

My working code looks like this:

extern "C" 
{
#include "common_header.h" 
#include "lip_image_processing.h" 
#include "lip_image_processing_internal.h" 
}
void exiv2(const char *jpg_filename, IMAGE *jpg_image)
{
    char data[256];
    Exiv2::ExifData::const_iterator exif_data_ptr, begin, end;
    Exiv2::Image::AutoPtr image;

    image = Exiv2::ImageFactory::open(jpg_filename);

    if(!image.get()) 
    {
        image_lib_program_error(__FILE__, __LINE__, __FUNC__,
            "can't read <%s>", jpg_filename);
    }

    image->readMetadata();
    Exiv2::ExifData &exifData = image->exifData();

    if(exifData.empty()) 
    {
        image_lib_program_warning(__FILE__, __LINE__, __FUNC__,
            "Exif data is empty in file <%s>", 
            strip_path_from_filename(jpg_filename));
        return;
    }

    begin    = exifData.begin();
    end        = exifData.end();

    for(exif_data_ptr = begin; exif_data_ptr != end; exif_data_ptr++) 
    {
        strncpy(data, exifData[exif_data_ptr->key()].toString().c_str(), 255);

        switch(exif_data_ptr->tag())
        {
            case EXIF_CAMERA_MODEL_TAG:
                strncpy(jpg_image->CameraModel, data, CAMERA_MODEL_STRING_LENGTH);
            break;

            case EXIF_ORIENTATION_TAG:
                jpg_image->orientation = atoi(data);
            break;

            case EXIF_DATETIME_TAG:
                strncpy(jpg_image->DateTime, data, DATETIME_STRING_LENGTH);
            break;

            default:
            break;
        }
    }

    printf
    (
        "%s\n\tcamera=\"%s\" datetime=\"%s\" orientation=%d\n", 
        jpg_filename, 
        jpg_image->CameraModel, jpg_image->DateTime, 
        jpg_image->orientation
    );
}

RE: Newbie writing a C wrapper for Exiv2 - Added by Robin Mills about 3 years ago

I'm a little lost, here. I see you marked this "[Solved]", so I guess we're done. Thank you for using Exiv2.

    (1-3/3)