A variable within an Inline use statement

T

Thomas

The following code works for me at the beginning of my own module which
uses Inline C 0.44:

use Inline (C => 'DATA',
LIBS => 'foo.lib',
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);

However, this variant:

my $lib_path = 'foo.lib';
use Inline (C => 'DATA',
LIBS => $lib_path,
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);

does not. It runs, but the string 'foo.lib' is not given as a library to
Inline's make process so that I end up with an error "unresolved
externals" when linking the DLL Inline creates as glue code. So a
literal string is fine in that particular context, a variable is not.
This is probably a basic language understanding problem of mine and has
less to do with the Inline module, but I can't figure this one out alone.
 
P

Peter Makholm

Thomas said:
However, this variant:

my $lib_path = 'foo.lib';
use Inline (C => 'DATA',
LIBS => $lib_path,
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);

does not.

Use statements are handled at compile time while you assignment is
executed at run time. That means tha you $lib_path variable gets
assigned after you have used Inline.pm.

The solution is to wrap you assignment in a BEGIN block.

//Makholm
 
B

Ben Morrow

Quoth Thomas said:
The following code works for me at the beginning of my own module which
uses Inline C 0.44:

use Inline (C => 'DATA',
LIBS => 'foo.lib',
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);

However, this variant:

my $lib_path = 'foo.lib';
use Inline (C => 'DATA',
LIBS => $lib_path,
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);

does not. It runs, but the string 'foo.lib' is not given as a library to
Inline's make process so that I end up with an error "unresolved
externals" when linking the DLL Inline creates as glue code. So a
literal string is fine in that particular context, a variable is not.
This is probably a basic language understanding problem of mine and has
less to do with the Inline module, but I can't figure this one out alone.

'use' statements are executed at compile time, but assignments are not
executed until runtime. This means that when the 'use Inline' line is
executed, $lib_path doesn't yet have a value.

There are three ways around this. By far the neatest is to use a
constant instead of a variable, as 'use constant' lines are also
executed at compile time:

use constant LIB_PATH => 'foo.lib';

use Inline C => 'DATA',
LIBS => LIB_PATH,
...;

but note that the expression in the 'use constant' line must *also* be
known at compile time, so if you need to calculate it you will need
something else.

The second is to use Inline->bind instead of 'use Inline':

use Inline;

my $lib_path = 'foo.lib';

Inline->bind(C => 'DATA', LIBS => $lib_path, ...);

but that has the disadvantage that the compiled functions won't be known
at compile time, so you will have to call them with parens. You also
can't use this if you are writing an installable module based on Inline:
see the Inline docs for details.

The third, which is ugly but flexible, is to perform the assignment in a
BEGIN block. Note that the 'my' has to come *outside* the BEGIN block,
as otherwise the variable is only scoped to the block:

my $lib_path;
BEGIN { $lib_path = 'foo.lib' }

use Inline C => 'DATA',
LIBS => $lib_path,
...;

Ben
 
S

sisyphus

The following code works for me at the beginning of my own module which
uses Inline C 0.44:

<plug>
If you're interested, InlineX::C2XS ( http://search.cpan.org/~sisyphus/InlineX-C2XS-0.13/
) can help you to remove the Inline::C dependency from your module.
It uses Inline::C to create the XS file (from your Inline C code) -
and can also write you a stub .pm and Makefile.PL.
</plug>

I personally think that Inline::C is the best thing since sliced bread
(and it astounds me that Ingy wants it to remain in its current,
unmaintained, state), but I don't like to see modules using it -
mainly because that adds an unnecessary dependency.

That's why I wrote (and use) InlineX::C2XS ... but it could probably
use some "outside assessment" - especially wrt the documentation.
So ... if (but *only* if) you're interested, give it a try and see if
it makes life simpler.

Cheers,
Rob
 
X

xhoster

Ben Morrow said:
'use' statements are executed at compile time, but assignments are not
executed until runtime. This means that when the 'use Inline' line is
executed, $lib_path doesn't yet have a value.

Why is this? Since Perl does compile time constant folding, why not do
compile time constant assignment as well? Is there a good reason not
to, or it just the way the cookie crumbles?

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
B

Ben Morrow

Quoth (e-mail address removed):
[
my $lib_path = "foo";
use Inline ..., $lib_path, ...;
]
Why is this? Since Perl does compile time constant folding, why not do
compile time constant assignment as well? Is there a good reason not
to, or it just the way the cookie crumbles?

I don't know. One sort-of good reason is that the variable must be
reassigned-to every time the block is entered (in the general case)
anyway, so it would be awkward to make the first assignment happen
early.

I would really like a Perl6ish

my $x :BEGIN = "foo";

construct. I wonder how hard that would be? Data::Alias must already
have most of what you need (tracing the boundaries of a particular
assignment and executing it specially)...

Ben
 
J

Joost Diepenmaat

Why is this? Since Perl does compile time constant folding, why not do
compile time constant assignment as well? Is there a good reason not
to, or it just the way the cookie crumbles?

Perl only does constant folding for actual constants. Which are never
variables. You can in fact make use of this at compile time:

#!/usr/bin/perl -w
use strict;
use constant PATH => "foo.lib" ;

use Inline (C => 'DATA',
LIBS => PATH,
BUILD_NOISY => 1,
FORCE_BUILD => 1,
);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top