[Ecls-list] Problems with updating an external global variable

Dietrich Bollmann dietrich at formgames.org
Wed Jul 24 02:23:40 UTC 2013


Hi Juanjo,

On Mon, Jul 22, 2013 at 5:12 AM, Juan Jose Garcia-Ripoll <
juanjose.garciaripoll at gmail.com> wrote:

>
> On Wed, Jul 17, 2013 at 11:32 AM, Dietrich Bollmann <
> dietrich at formgames.org> wrote:
>
>> Is my explanation more understandable this time?
>>
>
> I am afraid I am more confused now. Apart from the fact that your message
> appears full of markup (yellow word for some reason), the fact is that I do
> not see in this code the version that fails to work. You show me what works
> (and what you call a workaround), but I am not able to see what code fails
> for you.
>

Sorry for creating even more confusion - and thank you for putting this
amount of work into solving my problems!

The yellow markup probably results from using the "check spelling"
functionality in google mail...  I am pretty sure that I exited the
spelling mode before sending the mail - but for some reason the yellow
markup remained...  Sorry for that!

The reason that it is not possible to see problems in the code is that it
actually works: I found a different way to solve the problem and posted it
for reference.  Sorry for not making this clear enough.

Beside wanting to provide a working solution to my first question, I also
wondered if there was a better way to pack the pointer into a cl_object as
done in the function 'setRhinoCommandContext()'. Matthew answered to this
by telling me about 'ecl_make_pointer()' and 'ecl_to_pointer()' as
alternatives to my complicated approach.

So, rather than using

  union cl_lispunion cl_context_object;
  cl_context_object.foreign.t    = t_foreign;
  cl_context_object.foreign.tag  = ECL_SYM(":POINTER-VOID",1377);
  cl_context_object.foreign.size = 0;
  cl_context_object.foreign.data = (char*) &context;
  cl_object cl_context = &cl_context_object;

  cl_funcall(2, c_string_to_object("set-context"), cl_context);

I now simply use

  cl_funcall(2, c_string_to_object("set-context"),
ecl_make_pointer(&context));

Much better!

Thank you, Matthew!


> See for instance the example I attach. It consists on three different
> files all referring to the same constant. The code is working as it should
> according to your description, even when the lisp code is evaluated.
>
> I really believe you have some problem with "extern" or "static"
> declarations, or something more subtle, such as using lisp constants
> (defconstant) that the lisp is allowed to optimize away (assuming that they
> remain constant through execution).
>

I think the same.  The problem is, that I am still not clear about how
COMPILE-FILE and ASDF:MAKE-BUILD work in detail.  Also my main file is
written in C++ and not compiled from lisp.  But as the second approach
which is based on compiling the lisp code to a library and using a static
variable which only is accessed from the lisp setter and getter is more
elegant anyway, I just will continue with this solution.

For reference I attach two failing attempts based on a global variable
(v001, v002), the first working solution (v003) and the approach currently
used based on Matthew's advice (v004).  See the protocol at the end of the
mail for their usage.

Thanks again for your help!
Dietrich

===
Here, just for reference, a protocol showing the use of the attached
sources:

In a cygwin xterm:

unzip versions.zip

# Version 1
#
# - Based on an external global variable 'global_int'
# - Using COMPILE-FILE to build the object files and linking to them
directly
# - Cannot call the lisp function TEST

cd versions/v001

# Preparations:
#
#   - Makefile : adapt 'ECL_INSTALL_DIR' to the local installation dir of
ECL
#   - vsenv    : adapt 'vcvars64bat' to the location of vcvars64.bat

chmod 755 vsenv
./vsenv nmake
./main.exe

> global_int=123
>
> Condition of type: UNDEFINED-FUNCTION
> The function TEST is undefined.
> No restarts available.
> ...

./vsenv nmake clean

# Version 2
#
# - Based on an external global variable 'global_int'
# - Using ASDF:MAKE-BUILD to build a library
# - Cannot access the external symbol global_int

cd ../v002

# Preparations:
#
#   - Makefile : adapt 'ECL_INSTALL_DIR' to the local installation dir of
ECL
#   - vsenv    : adapt 'vcvars64bat' to the location of vcvars64.bat

chmod 755 vsenv
./vsenv nmake

> ...
> main.obj : error LNK2001: unresolved external symbol global_int
> main.exe : fatal error LNK1120: 1 unresolved externals
> ...

./vsenv nmake clean

# version 3
#
# - Based on a static variable 'global_context' only accessed from inside
the library
# - 'global_context' is set from C++ by calling a compiled lisp setter
function
# - Using ASDF:MAKE-BUILD to build a library
# - Works - but uses a complicated approach to wrap the pointer into a
cl_object

cd ../v003

# Preparations:
#
#   - Makefile : adapt 'ECL_INSTALL_DIR' to the local installation dir of
ECL
#   - vsenv    : adapt 'vcvars64bat' to the location of vcvars64.bat

chmod 755 vsenv
./vsenv nmake
./main.exe

> global_context = NULL
> *global_context = 123

./vsenv nmake clean

# version 4
#
# - Based on a static variable 'global_context' only accessed from inside
the library
# - 'global_context' is set from C++ by calling a compiled lisp setter
function
# - Using ASDF:MAKE-BUILD to build a library
# - Works - version currently used

cd ../v004

# Preparations:
#
#   - Makefile : adapt 'ECL_INSTALL_DIR' to the local installation dir of
ECL
#   - vsenv    : adapt 'vcvars64bat' to the location of vcvars64.bat

chmod 755 vsenv
./vsenv nmake
./main.exe

> global_context = NULL
> *global_context = 123

./vsenv nmake clean

# fin.


Juanjo
>
>

On Wed, Jul 24, 2013 at 11:08 AM, Dietrich Bollmann
<dietrich at formgames.org>wrote:

> Hi Matt,
>
> Thanks for your answer - and sorry for my late reply!
>
> On Thu, Jul 18, 2013 at 2:39 AM, Matthew Mondor <mm_lists at pulsar-zone.net>
>  wrote:
>
> On Sun, 14 Jul 2013 00:31:27 +0900
>> Dietrich Bollmann <dietrich at formgames.org> wrote:
>>
>> > I compiled my ECL lisp functions with asdf:make-build into a library.
>> >
>> > Some functions depend on the value of a global variable which has to be
>> set
>> > in the code using the library.
>> >
>> > But when changing the value of the global variable in the code using the
>> > library, the library functions still use the old value...
>>
>> I don't really understand why in your example code only the original
>> value is obtained, possibly that the scope of the variable is not the
>> expected one (that there are two such variables or such)?  I recommend
>> to use (setf c::*delete-files* nil) and to inspect the resulting C code.
>>
>
> I seem to be unable to understand myself.
>
> But approaching the problem by
>
>   - using a static variable together with a lisp setter and getter and
>   - compiling the lisp files to a library with ASDF:MAKE-BUILD
>
> results in a working solution.  This one is more elegant anyway, so I will
> just continue with this one.
>
> Just for reference I'll send the sources of two failing attempts as well
> as those of two working solutions to the list.  See the attachment to the
> next email responding to Juanjo's answer.
>
>
>> Note also that for handling foreign pointers (other than :pointer-void
>> with C-INLINE which it handles implicitely), there are the public
>> interfaces ecl_make_pointer() and ecl_to_pointer().
>>
>
> Thanks!
>
> These are the functions I was looking for!
>
>
>> In your next message I see that you seem to be doing it right to store
>> the context in a C variable (although I didn't test your code).  If
>> it's to store a unique global context on which the Lisp code should
>> have no control, it might not matter, but otherwise, it might be best
>> to have interface functions require the context parameter or to obtain
>> it from a dynamic/special variable, which would allow Lisp code to
>> handle multiple objects more elegantly than is generally possible from
>> C/C++ because of the power of dynamic scope...
>>
>
> What do you mean by "dynamic/special variable"?
>
> But anyway, I rewrote my solution as mentioned before and now use
> 'ecl_make_pointer()' rather than my own complicated way to wrap the pointer
> (See the forth version in the code attached to the answer to Juanjo).  This
> looks good enough to me and I will use this one from now on!
>
> Thanks again for your help!
>
> Cheers,
> Dietrich
>
>
>> --
>> Matt
>
>
>
> On Thu, Jul 18, 2013 at 2:39 AM, Matthew Mondor <mm_lists at pulsar-zone.net>wrote:
>
>> On Sun, 14 Jul 2013 00:31:27 +0900
>> Dietrich Bollmann <dietrich at formgames.org> wrote:
>>
>> > I compiled my ECL lisp functions with asdf:make-build into a library.
>> >
>> > Some functions depend on the value of a global variable which has to be
>> set
>> > in the code using the library.
>> >
>> > But when changing the value of the global variable in the code using the
>> > library, the library functions still use the old value...
>>
>> I don't really understand why in your example code only the original
>> value is obtained, possibly that the scope of the variable is not the
>> expected one (that there are two such variables or such)?  I recommend
>> to use (setf c::*delete-files* nil) and to inspect the resulting C code.
>>
>> Note also that for handling foreign pointers (other than :pointer-void
>> with C-INLINE which it handles implicitely), there are the public
>> interfaces ecl_make_pointer() and ecl_to_pointer().
>>
>> In your next message I see that you seem to be doing it right to store
>> the context in a C variable (although I didn't test your code).  If
>> it's to store a unique global context on which the Lisp code should
>> have no control, it might not matter, but otherwise, it might be best
>> to have interface functions require the context parameter or to obtain
>> it from a dynamic/special variable, which would allow Lisp code to
>> handle multiple objects more elegantly than is generally possible from
>> C/C++ because of the power of dynamic scope...
>> --
>> Matt
>>
>>
>> ------------------------------------------------------------------------------
>> See everything from the browser to the database with AppDynamics
>> Get end-to-end visibility with application monitoring from AppDynamics
>> Isolate bottlenecks and diagnose root cause in seconds.
>> Start your free trial of AppDynamics Pro today!
>>
>> http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
>> _______________________________________________
>> Ecls-list mailing list
>> Ecls-list at lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/ecls-list
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20130724/69077dc8/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: versions.zip
Type: application/zip
Size: 13341 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20130724/69077dc8/attachment.zip>


More information about the ecl-devel mailing list