On Dec 8, 9:43 pm, [EMAIL PROTECTED] (Allswellthatendswell) wrote: > Hello. I read Alexander Kolbasov's excellent blog on the pitfalls > of Perl XS with enums. I used the following xs_test.h and got > Alexander's h2xs fixes to work the way the blog described. > > // xs_test.h > typedef enum mdNameNameHints { > NameFull=1, > NameInverse=2, > NameGovernmentInverse=4, > NameMixedFirst=8, > NameMixedLast=16} xst_NameHints_t; > > I am now trying to call a C function by passing in one of these enum > values in perl 5.8.8. This is the perl script: > > use mdNamePerl; > my $g; > #Create > mdName Object$g=&mdNamePerl::mdNameCreate(); > &mdNamePerl::mdNameSetPrimaryNameHint($g,NameFull); > > mdNamePerl is a Perl XS application which glues a C/C++ application > together with Perl. > > The C prototype I am trying to access is : > MDAPI int __stdcall mdNameSetPrimaryNameHint(mdName, enum > mdNameNameHints); > > In the typemap, I have mapped enum mdNameNameHints to a T_IV(integer) > but when I run this perl program I get the error : Argument "NameFull" > isn't numeric in entersub at test.pl line 66, <CONFIG> chunk 39. > > Does anyone have any ideas how I can pass the enumeration NameFull > to the perl subroutine call correctly given that I have > implemented(hopefully correctly) the h2xs fixes in Alexander's > blog ,"Pitfals of the Perl XS or what to do when things do not work as > advertised"? Thank you very much.
I have found out the source of the problem. Yesterday, I was running my tests on a Sun Solaris 8 which did not have have the perl package ExtUtils::Constant installed. Today, I changed to Red Hat Enterprise Linux 5.1 which has the perl package ExtUtils::Constant installed. Thank you. Here is my Perl test program and the MakeFile.PL #XS-Test1.t # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl XS- Test1.t' # change 'tests => 2' to 'tests => last_test_to_print'; use Test::More tests => 22; BEGIN { use_ok('XS::Test1') }; my $fail = 0; foreach my $constname (qw( Aggressive Blank ConfigFile Conservative DatabaseExpired Female FirstLast Formal Informal Male Mixed NameFull NameGovernmentInverse NameInverse NameMixedFirst NameMixedLast Neutral NoError Slug Unknown)) { next if (eval "my \$a = $constname; 1"); if ($@ =~ /^Your vendor has not defined XS::Test1 macro $constname/) { print "# pass: $@"; } else { print "# fail: $@"; $fail = 1; } } ok( $fail == 0 , 'Constants' ); ######################## # Insert your test code below, the Test::More module is use()ed here so read # its man page ( perldoc Test::More ) for help writing this test script. is(NoError,0); is(ConfigFile,1); is(DatabaseExpired,2); is(Unknown,3); is(NameFull,1); is(NameInverse,2); is(NameGovernmentInverse,4); is(NameMixedFirst,8); is(NameMixedLast,16); is(Male,1); is(Mixed,2); is(Female,3); is(Aggressive,1); is(Neutral,2); is(Conservative,3); is(Formal,0); is(Informal,1); is(FirstLast,2); is(Slug,3); is(Blank,4); my $record; my $g; #Create mdName Object $g=&XS::Test1::mdNameCreate(); #Set Master License String &XS::Test1::mdNameSetLicenseString($g,"b1cac9c8cfcc0162"); #Set Path to Name File &XS::Test1::mdNameSetPathToNameFiles($g,"/home/frankc/Test/ mdNameTest/Distribution"); if(&XS::Test1::mdNameInitializeDataFiles($g) != NoError) { diag( "Failed to Initialize mdName::mdName ". &XS::Test1::mdNameGetInitializeErrorString($g)."\n"); } #Check build number method diag( "Build Number: " .&XS::Test1::mdNameGetBuildNumber($g). "\n") ; #Database Date diag( "Database Date: " .&XS::Test1::mdNameGetDatabaseDate($g). "\n"); #Check expiration date diag( "Expiration Date: " .&XS::Test1::mdNameGetExpirationDate($g). "\n"); &XS::Test1::mdNameSetFirstNameSpellingCorrection($g,1); # open file handle open CONFIG, "/home/frankc/Test/mdNameTest/Distribution/DemoData/ mdName.sdf"; while ($record = <CONFIG>) { $record =~ s/^\s+//; #remove leading whitespaces $record =~ s/\s+$//; #remove trailing whitespaces diag( "FullName: " .$record. "\n"); &XS::Test1::mdNameClearProperties($g); &XS::Test1::mdNameSetFullName($g,$record); &XS::Test1::mdNameSetPrimaryNameHint($g,NameFull); &XS::Test1::mdNameSetSecondaryNameHint($g,NameInverse); # Parse the fullname &XS::Test1::mdNameParse($g); #Gender diag( "Gender: " .&XS::Test1::mdNameGetGender($g). "\n"); #Prefix diag( "Prefix: " .&XS::Test1::mdNameGetPrefix($g). "\n"); #First Name diag( "First Name: " .&XS::Test1::mdNameGetFirstName($g). "\n"); #Middle Name diag( "Middle Name: " .&XS::Test1::mdNameGetMiddleName($g). "\n"); #Last Name diag( "Last name: " .&XS::Test1::mdNameGetLastName($g). "\n"); #Suffix diag( "Suffix: " .&XS::Test1::mdNameGetSuffix($g). "\n"); #Gender2 diag( "Gender 2: " .&XS::Test1::mdNameGetGender2($g). "\n"); #Prefix2 diag( "Prefix 2: " .&XS::Test1::mdNameGetPrefix2($g). "\n"); #First Name2 diag( "First Name 2: " .&XS::Test1::mdNameGetFirstName2($g). "\n"); #Middle Name2 diag( "Middle Name 2: " .&XS::Test1::mdNameGetMiddleName2($g). "\n"); #Last Name2 diag( "Last name 2: " .&XS::Test1::mdNameGetLastName2($g). "\n"); #Suffix2 diag( "Suffix2: " .&XS::Test1::mdNameGetSuffix2($g). "\n"); #Salutation diag( "Salutation: " .&XS::Test1::mdNameGetSalutation($g). "\n"); #Status Code diag( "Status Code: " .&XS::Test1::mdNameGetStatusCode($g). "\n"); #Error Code diag( "Error Code: " .&XS::Test1::mdNameGetErrorCode($g). "\n"); #Change Code diag( "Change Code: " .&XS::Test1::mdNameGetChangeCode($g). "\n"); } close CONFIG; ########################################################################################## #MakeFile.PL use 5.008008; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'XS::Test1', VERSION_FROM => 'lib/XS/Test1.pm', # finds $VERSION PREREQ_PM => {}, # e.g., Module::Name => 1.1 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/XS/Test1.pm', # retrieve abstract from module AUTHOR => 'Frank Chang <[EMAIL PROTECTED]>') : ()), LIBS => ['-L/home/frankc/Test/mdNameTest/liunkg_deb - lmdName'], # e.g., '-lm' DEFINE => '', # e.g., '-DHAVE_SOMETHING' INC => '-I.', # e.g., '-I. -I/usr/include/other' # Un-comment this if you add C files to link with later: # OBJECT => '$(O_FILES)', # link all the C files too ); if (eval {require ExtUtils::Constant; 1}) { # If you edit these definitions to change the constants used by this module, # you will need to use the generated const-c.inc and const-xs.inc # files to replace their "fallback" counterparts before distributing your # changes. my @names = ({name=>"Aggressive", macro=>"1"}, {name=>"Blank", macro=>"1"}, {name=>"ConfigFile", macro=>"1"}, {name=>"Conservative", macro=>"1"}, {name=>"DatabaseExpired", macro=>"1"}, {name=>"Female", macro=>"1"}, {name=>"FirstLast", macro=>"1"}, {name=>"Formal", macro=>"1"}, {name=>"Informal", macro=>"1"}, {name=>"Male", macro=>"1"}, {name=>"Mixed", macro=>"1"}, {name=>"NameFull", macro=>"1"}, {name=>"NameGovernmentInverse", macro=>"1"}, {name=>"NameInverse", macro=>"1"}, {name=>"NameMixedFirst", macro=>"1"}, {name=>"NameMixedLast", macro=>"1"}, {name=>"Neutral", macro=>"1"}, {name=>"NoError", macro=>"1"}, {name=>"Slug", macro=>"1"}, {name=>"Unknown", macro=>"1"}); ExtUtils::Constant::WriteConstants( NAME => 'XS::Test1', NAMES => [EMAIL PROTECTED], DEFAULT_TYPE => 'IV', C_FILE => 'const-c.inc', XS_FILE => 'const-xs.inc', ); } else { use File::Copy; use File::Spec; foreach my $file ('const-c.inc', 'const-xs.inc') { my $fallback = File::Spec->catfile('fallback', $file); copy ($fallback, $file) or die "Can't copy $fallback to $file: $!"; } }