tags:

views:

142

answers:

1

UPDATE: appologies for the wrong place I chose to put stuff. I didn't notice those adds @Sinan mentioned at all probably they had been blocked by my browser. Anyway I've deleted the links now. and thank you guys :)

In my [previous post][1], @daotoad mentioned an Inline module. Now I'm playing around with it. Well, actually except for Perl, I basically know nothing about any other programming languages. The script is written for pure fun. I want to see if I can just throw to my Perl script some code written in other programming language and somehow get it working.

Well, I copied a CPP source code which I found on the Net to my Perl script and I've been trying to get it working but all I get is a screenful of error message: It looks like something's suspicious with the imported CPP libary but I'm not sure. The following information is part of the error information that caught my eyes:

E:/solarlunar.h:53: error: expected identifier before "false"
E:/solarlunar.h:53: error: expected `}' before "false"
E:/solarlunar.h:53: error: expected unqualified-id before "false"
E:/solarlunar.h:53: error: expected declaration before '}' token
In file included from _3_pl_62cb.xs:19:
E:/solarlunar.h:1:1: unterminated #ifndef
NMAKE : fatal error U1077: 'C:\WINDOWS\system32\cmd.exe' : return code '0x1'
Stop.

A problem was encountered while attempting to compile and install your Inline
CPP code. The command that failed was:
  nmake > out.make 2>&1

I've checked the 53rd line of solarlunar.h file and after a little bit of google about what it might mean I think this line looks pretty innocent but well as a complete C++ newbie I'm not sure:

**typedef enum boolean { false = 0, true = 1 } boolean;** 

I've tried compiling and testing the C++ code with DEV-C++ and everything worked like expected.

My script (updated) is this:

    #Inline-Test.pl
 use warnings;
 use Inline 'CPP' => Config => LIBS => 'E:/';
    use Inline 'CPP' => Config => INC  => 'E:/';
 use Inline 'CPP';

    my $args = <STDIN>;     
 chomp $args;
    my $result = main($args); 
    print $result;

__END__
__CPP__


#include <stdio.h>
#include <stdlib.h>
#include "solarlunar.h"
#include "solarlunar.c"

/**//* input format: sl -[s|l]   year.month.day */
/**//* the lunar calendar date range is limited by solarlunar.h: 1899/12/1 ~ 2099.12.30 */

static void usage(void);

int main(int argc, char *argv[])
{
    int year, month, day;
    int i;
    /**//* convert flag, 0: solar convert to luanr. 1: lunar convert solar */
    int convert_f = 0;
    solar_calendar so;
    lunar_calendar lu;

    /**//* input check */
    if( argc < 3 || argv[1][0]!= '-' ||
         !(argv[1][2] == 's' || argv[1][3] == 'l')) {
        usage();
        exit(1);
    }

    /**//* get convert flag */
    convert_f = (argv[1][4] == 's' ? 0 : 1);

    /**//* converting */
    for(i = 2; i < argc; i++) {
        sscanf(argv[i], "%d.%d.%d", &year, &month, &day);
        switch(convert_f) ...{
            case 0:
                so = solar_creat_date(year, month, day);
                lu = solar2lunar(so);
                printf("%d.%d.%d ", lunar_get_year(lu), lunar_get_month(lu), lunar_get_day(lu));
                break;
            case 1:
                lu = lunar_creat_date(year, month, day);
                so = lunar2solar(lu);
                printf("%d.%d.%d ", solar_get_year(so), solar_get_month(so), solar_get_day(so));
                break;
            default :
                exit(2);
        }
    }
        return 0;
}


static void usage(void)
{
    printf("sl -[s|l] year1.month1.day1 year2.month2.day2 ... "
            "-s: solar calendar date convert to lunar calendar date. "
            "-l: lunar calendar date convert to lunar calendar date.");
}

The necessary library can be downloaded from [here] and [here]. Sorry, wrong place to put stuff. links now deleted.

+3  A: 

Your problem stems from the fact that you are trying to compile C source code as C++. The author of this silly program seems want a boolean type in C and therefore defines it using an enumeration:

typedef enum boolean { false = 0, true = 1} boolean; 

Now, this trips up a C++ compiler because that language has a bool type and true and false are values for that type. The assignment false = 0 is not valid C++.

It is interesting that the word boolean only appears in one place in solarlunar.c:

boolean is_leap_year(const int year)
{
    return LEAP(ABS(year));
}

changing that function's return type to int and getting rid of the typedef in solarlunar.h should solve the immediate issue. Compiling the source code as C using gcc resulted in no errors even without those changes.

Sinan Ünür
@Sinan, thanks for posting this answer. It sounds like the answer :) Thanks and thanks for the harsh criticism you posted.
Mike
@Sinan, it still does not work. Like you suggested, I used int is_leap_year(const int year){return LEAP(ABS(year));} in the .c file and in the .h file I deleted the 53rd line that contains boolean and the 64th line that also contains boolean is_leap_year(const int year) but it is still not working :( Windows console threw me some different error messages. I'm wondering whether you have tested the script on Unix or Windows. Thanks.
Mike
and it does not work if I change in the 64th line of .h file boolean is_leap_year(const int year) to int is_leap_year(const int year)
Mike
@Sinan, can you kindly claify this "Compiling the source code as C using gcc resulted in no errors"? I mean have you tested the Inline::CPP module? I can't get my Perl script working. But like I said I had successfully compiled the C++ source code using DEV-C++. Now I let the Perl script use C compiler to comile the wrapped source, but I still can't get it working :(
Mike
@Mike I compiled `solarlunar.c` from the `cmd.exe` shell using `gcc version 3.4.5 (mingw-vista special r3)` (which I installed using `ppm`). By default, `gcc` treats files with extension `.c` as `C` source, not `C++`, and therefore, the definition of the `boolean` enum did not cause any errors (there were a couple warnings, but the code is a little amateurish anyway). In any case, I do not understand why you insist on using `Inline::CPP` when you are trying to use `C` code. The right way to go about this is to compile `solarlunar.c` and then link to it. But, I am not motivated to work it out.
Sinan Ünür
@Sinan, thank you for the explanation. Looks like using the "C" compiler in my Perl script can get the source "C++" code working just fine. The problem I'm now facing is, I've realized, caused by the fact that I lack a good understanding of Perl. But I'll get it working anyway, I'm sure :)
Mike
@Sinan, the "C++" code I'm using is copied from a website that says "it's C++ code" and the problem is I can't tell the difference between C++ and C. I'm just having fun with Perl :) and want to learn.
Mike
@Sinan, I actually wrote some time ago a pure Perl program without using any module that can convert between solar and lunar calendar and do some other stuff. my code is probably very ugly though. the thing is I just want to have fun and gain Perl experience.
Mike
@Sinan, although I'm still having trouble with this Inline thing, my original problem is gone. Answer happily accepted and thanks again :)
Mike
@Sinan, looks like the Inline::C module cannot handle "int main(int argc, char *argv[])" that appears in the wrapped C code, so I have to give up on it for now.
Mike