[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problems with IDL call_external to C shared object



Streun Andreas wrote:
> 
> Hello -
> 
> who is experienced in running IDL with C shared objects?
> 
> I'm trying to make an IDL GUI for a rather complex C batch
> program. The effects are rather strange: sometimes it works
> perfectly, but mostly it doesn't:  suddenly on the C-side strange
> and wrong number appear in calculations leading to crashes. It seems
> like something is initialized or dereferenced in a wrong way.
> However the behaviour is determinsitic: a small change in the IDL
> program like declaring a new variable anywhere causes the crash,
> after undoing the change it works well again. Maybe a memory conflict ?
> 
> The C-program alone in batch mode runs reliably. It does a lot of
> mallocs but never frees any memory (because it is batch).
> IDL communicates via the CALL_EXTERNAL function.
> I'm rather sure that I have checked the variables on both sides of the
> fence are really of same type. (However I'm a poor C-programmer...)
> I'm using IDL 5.3 on a Linux system and the GNU C-compiler.
> 
> Now the questions:
> 
> - Is it possible that IDL overwrites or frees memory allocated by the C
> shared object ? Is there a general way to prevent it from doing so ?
> 
> - What is the effect of the /CDECL keyword to CALL_EXTERNAL ?
> I tried with and without but no success.
> 
> - Is it possible that the C program "forgets" something between
> the IDL CALL_EXTERNALs ?
> 
> (important:)
> - Is there an opinion whether this problem can be solved in principle
> and within finite time ?!
> 
> (has nothing to do with the problem but I would like to know:)
> - How can I return an array via CALL_EXTERNAL or have I always
> to loop over calls returning scalars ? The EZCA  library (channel
> access to EPICS control system) manages to return arrays, but I
> couldn't figure out how.
> 
> Thanks for any help.


The best way to use call_external I've found is to allocate all arrays,
variables, and strings on the IDL side and directly manipulate them
within the C program.  Most variable types do *not* map directly between
IDL and C.  Did you take a good look at
$IDL_DIR/external/call_external/C/, which contains lots of (small)
examples?  Also see the "external.h" header for lots of info.

Another bit of confusion:  IDL simply calls the function directly from
the shared library specified... the function is not at all linked in
(other than existing in a shared program stack), and variables will not
be preserved through successive function calls (unless they are declared
static or global).  

An example of passing an array as a variable:
IDL_LONG showarray(int argc, void *argv[]) {
  float *arr;
  IDL_MEMINT *n_elem,i;
  arr=(float *) argv[0];
  n_elem=(IDL_MEMINT *) argv[1];
  printf("%d\n",*n_elem);
  for(i=0;i<*n_elem;i++)
	printf("%d: %f\n",i,arr[i]); /* Don't printf, it's not nice! */
  return 1;
}

which would be called via, e.g.:

IDL> ret=call_external('mylib.so','showarray',findgen(10),10)

Presumably if your code allocates it's own memory without cleaning up
after itself, it will be rather unstable.  Unless you need to return
arrays of dynamic size/type, the originate-all-data-in-IDL method will
much simplify your life.

Good luck,

JD

-- 
 J.D. Smith                  |   WORK: (607) 255-6263
 Cornell Dept. of Astronomy  |         (607) 255-5842
 304 Space Sciences Bldg.    |    FAX: (607) 255-5875  
 Ithaca, NY 14853            |