Calling C Programs from IDL

Here are some general tips for using Call_External.

  • All arrays which need to be passed between IDL and C must be allocated in IDL. This includes both arrays being passed from IDL to C and from C back to IDL. Sometimes this requires an initial call to the C code to return the array sizes which IDL will allocate, if the array sizes are not known to IDL beforehand.
  • Don't deallocate any arrays which were passed from IDL.
  • Don't pass strings, rather pass byte arrays. It is much simpler. Convert strings to byte arrays in IDL before or after the Call_External call.
  • Convert all output variables to the data type which C is expecting in the Call_External call.

Question: What is the effect of the /CDECL keyword to Call_External?

Answer: This controls the calling convention. If your C function is being called then you probably have this set correctly.

Question: Is it possible that the C program "forgets" something between the IDL Call_External calls?

Answer: Yes, it will forget anything which is not global or static.

Question: How can I return an array via Call_External or have I always to loop over calls returning scalars ?

Answer: Here is a simple example. It is C code which computes the Mandelbrot set, and is called from IDL. The argv[7] argument is a 2-D array.

   void mandelbrot(int argc, void *argv[])
   {
    int nr = *(int *) argv[0];
    int ni = *(int *) argv[1];
    double rstart = *(double *) argv[2];
    double istart = *(double *) argv[3];
    double dr = *(double *) argv[4];
    double di = *(double *) argv[5];
    int max_iter = *(int *) argv[6];
    int *result =  argv[7];
   int i, j, count;
    double real, imag, rz, iz, sz2, rz2, iz2;
       for (i=0; i<ni; i++) {
         imag = istart + i*di;
         for (j=0; j<nr; j++) {
              real = rstart + j*dr;
              rz = 0.;
              iz = 0.;
              sz2 = 0.;

              count = 0;
              while ((count < max_iter) && (sz2 < 4.0)) {
                   rz2 = rz * rz;
                   iz2 = iz * iz;
                   iz = 2.0 * rz * iz + imag;
                   rz = rz2 - iz2 + real;
                   sz2 = rz2 + iz2;
                   count++;
              }
              *result++ = count;
         }
       }
   }

Here is the IDL code which calls the C code:

   function mandelbrot1, xcenter, ycenter, radius, size, max_iter, xout, yout
   if (n_elements(size) eq 0) then size=100
   if (n_elements(max_iter) eq 0) then max_iter=255
   dx = double(radius)*2/size
   xstart = double(xcenter - radius)
   xstop = double(xcenter + radius)
   ystart = double(ycenter - radius)
   ystop = double(ycenter + radius)
   result = lonarr(size, size)
   xout = xstart + findgen(size)*dx
   yout = ystart + findgen(size)*dx
   s = call_external('mandelbrot.dll', 'mandelbrot', $
                      long(size), $
                      long(size), $
                      double(xstart), $
                      double(ystart), $
                      double(dx), $
                      double(dx), $
                      long(max_iter), $
                      result)
   return, result
   end

Question: Can I pass IDL structures to my C program using Call_External?

Answer: [From 4 APRIL 1996] The last time I looked, the means by which structures are passed was intentionally not documented, presumably so that RSI would be free to change it in the future.

However, I know by experience that IDL presently passes structures just like you would expect (i.e. it passes the address of the start of the structure). All structure elements except strings are contained in the structure itself (i.e. the structure contains the value, not a pointer). Strings are different: the structure contains either the descriptor or the address of the descriptor (I forget).

I routinely pass structures to Call_External, but I do so at my own risk, since it is not guaranteed to be done the same way in future versions of IDL.

I have found that the structures will contain padding to keep the members aligned on natural boundaries. The C compiler will normally do this on the structures in yourCall_External code as well, so it has not been a problem.

WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行双向通信,极大地提高了实时性,被广泛应用于即时通讯、在线游戏、股票交易等领域。本篇将详细讲解如何使用C#来实现WebSocket,以及Fleck库在其中的作用。 WebSocket协议基于HTTP的握手过程,但一旦连接建立,它就不再依赖HTTP,而是通过TCP直接通信。在C#中,我们可以利用.NET Framework或.NET Core提供的System.Net.WebSockets命名空间来创建WebSocket服务器和客户端。然而,对于更高级的功能和更好的灵活性,开发者通常会选择第三方库,如Fleck。 Fleck是C#中一个轻量级且高效的WebSocket服务器实现。它提供了丰富的事件驱动API,使得开发者可以轻松地处理WebSocket连接的建立、消息传递和断开等操作。下面我们将探讨Fleck的使用步骤: 1. **安装Fleck**:你需要在你的项目中添加Fleck库。如果你使用的是NuGet包管理器,可以通过搜索"Fleck"并安装来获取。 2. **初始化服务器**:在C#代码中,首先创建一个Fleck服务器实例,指定监听的IP地址和端口号。例如: ```csharp var server = new Fleck.WebSocketServer("ws://localhost:8080"); ``` 3. **配置服务器**:你可以设置各种配置选项,如最大接收/发送缓冲区大小、心跳间隔等。然后注册事件处理器,如OnOpen、OnClose、OnMessage等,以处理客户端连接、断开和消息接收。 4. **连接事件**:`OnOpen`事件在客户端连接时触发,你可以在这里对新连接进行初始化操作,如存储连接信息、验证用户等。 5. **消息处理**:`OnMessage`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值