您的位置:首页 > 编程语言 > C语言/C++

Calling C and C++ from IDL (三) ——数组传递

2016-04-11 19:51 741 查看
在IDL与C/C++混合编程的过程中,经常会遇到数据之间的传递,其中,数组的传递非常普遍。本文将简单介绍如何在IDL与C/C++之间进行数据传递。在上一篇文章中,介绍了变量传递,这里将在此基础上修改部分内容。

第一步:首先在IDLtoC.h文件中添加如下代码:

/*IDLtoCarrayExamples.c*/
extern void IDLtoC_arrayExample_exit_handler(void);
extern int IDLtoC_arrayExampleStartup(void);


目的是添加启动函数和exit_handler,与上一篇传递变量的作用一致。

第二步:在IDLtoC.c文件中编写如下代码:

if (!IDLtoC_arrayExampleStartup())
{
IDL_MessageFromBlock(msg_block, IDLtoC_ERROR, IDL_MSG_RET, "Unable to initialize C array example");
}


这段代码需要放置在IDL_Load函数中,因为IDL_Load函数是与IDL进行交互的接口。

第三步:新建一个IDLtoCarrayExamples.c文件

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "export.h"
#include "IDLtoC.h"
/*global here*/
static char statusBuffer[256];
/*函数原型*/
extern void IDL_CDECL IDLtoC_arrayInPlace(int argc, IDL_VPTR argv[], char *argk);
extern IDL_VPTR IDL_CDECL IDLtoC_singleIntArray(int argc, IDL_VPTR argv[], char *argk);
/*define the functions*/
static IDL_SYSFUN_DEF2 IDLtoC_functions[]=
{
{IDLtoC_singleIntArray,"IDLTOC_SINGLEINTARRAY",1,1,0,0},
};
static IDL_SYSFUN_DEF2 IDLtoC_procedures[]=
{
{ (IDL_FUN_RET)IDLtoC_arrayInPlace, "IDLTOC_ARRAYINPLACE", 1, 1, 0, 0 },
};
/*check which system we are on*/
#ifdef WIN32
#include<Windows.h>
#endif

/*startup call when DLM is loaded*/
int IDLtoC_arrayExampleStartup(void)
{
if (!IDL_SysRtnAdd(IDLtoC_functions, TRUE, ARRLEN(IDLtoC_functions)))
{
return IDL_FALSE;
}
if (!IDL_SysRtnAdd(IDLtoC_procedures, FALSE, ARRLEN(IDLtoC_procedures)))
{
return IDL_FALSE;
}
/*register the exit handler*/
IDL_ExitRegister(IDLtoC_arrayExample_exit_handler);
return (IDL_TRUE);
}
/*Called when IDL is shutdown*/
void IDLtoC_arrayExample_exit_handler(void)
{
/*nothing special to do in this case*/
}
IDL_VPTR IDL_CDECL IDLtoC_singleIntArray(int argc, IDL_VPTR argv[], char * argk)
{
int ndims, numElements, i;
char *pbInArray, *pbOutArray;
short *psInArray, *psOutArray;
int *piInArray, *piOutArray;
float *pfInArray, *pfOutArray;
double *pdInArray, *pdOutArray;
IDL_VPTR ivFloatArray, ivDoubleArray, ivLongArray, ivShortArray, ivByteArray;

IDL_ENSURE_ARRAY(argv[0]);
ndims = argv[0]->value.arr->n_dim;
numElements = argv[0]->value.arr->n_elts;

switch (argv[0]->type)
{
case IDL_TYP_BYTE:
/*create the output array*/
pbOutArray = IDL_MakeTempArray((int)IDL_TYP_BYTE,  ndims, argv[0]->value.arr->dim, IDL_ARR_INI_ZERO, &ivByteArray);
/*Pull out the data from IDL*/
pbInArray = (char*)argv[0]->value.arr->data;
/*send a message back to IDL*/
sprintf(statusBuffer, "You send a byte array");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
/*change the data a little*/
for (i = 0; i < numElements; i++)
{
pbOutArray[i] = pbInArray[i] + 10;

}
/*return the result*/
return ivByteArray;
case IDL_TYP_INT:
psOutArray = (short*)IDL_MakeTempArray((int)IDL_TYP_INT, ndims, argv[0]->value.arr->dim, IDL_ARR_INI_ZERO, &ivShortArray);
psInArray = (short*)argv[0]->value.arr->data;
sprintf(statusBuffer, "You send an integer array");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
for (i = 0; i < numElements; i++)
{
psOutArray[i] = psInArray[i] - 25;
}
return ivShortArray;
case IDL_TYP_LONG:
piOutArray = (int*)IDL_MakeTempArray((int)IDL_TYP_LONG, ndims, argv[0]->value.arr->dim, IDL_ARR_INI_ZERO, &ivLongArray);
piInArray = (int*)argv[0]->value.arr->data;
sprintf(statusBuffer, "You send an long array");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
for (i = 0; i < numElements; i++)
{
piOutArray[i] = piInArray[i] * 2;
}
return ivLongArray;
case IDL_TYP_FLOAT:
pfOutArray = (float*)IDL_MakeTempArray((int)IDL_TYP_FLOAT, ndims, argv[0]->value.arr->dim, IDL_ARR_INI_ZERO, &ivFloatArray);
pfInArray = (float*)argv[0]->value.arr->data;
sprintf(statusBuffer, "You send an float array");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
for (i = 0; i < numElements; i++)
{
pfOutArray[i] = pfInArray[i] * 2.0;
}
return ivFloatArray;
case IDL_TYP_DOUBLE:
pdOutArray = (double*)IDL_MakeTempArray((int)IDL_TYP_DOUBLE, ndims, argv[0]->value.arr->dim, IDL_ARR_INI_ZERO, &ivDoubleArray);
pfInArray = (double*)argv[0]->value.arr->data;
sprintf(statusBuffer, "You send an integer array");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
for (i = 0; i < numElements; i++)
{
pdOutArray[i] = pdInArray[i] /2.0;
}
return ivDoubleArray;
case IDL_TYP_STRING:
IDL_MessageFromBlock(msg_block, IDLtoC_NOSTRINGARRAY, IDL_MSG_LONGJMP, "in IDLtoC_singleIntArray()");
break;
default:
sprintf(statusBuffer, "You send an array type that was not modified");
IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, statusBuffer);
return (IDL_GettmpLong(-1));
}
}
void IDL_CDECL IDLtoC_arrayInPlace(int argc, IDL_VPTR argv[], char *argk)
{
/*
Called in IDL as
inputArray=intarr(5)
IDLtoC_arrayInPlace,inputArray
print,inputArray
help,inputArray
*/
int ndim, numElements, i;
double *pbOutArray;
IDL_VPTR vpTmp;

IDL_EXCLUDE_EXPR(argv[0]);
IDL_ENSURE_ARRAY(argv[0]);
ndim = argv[0]->value.arr->n_dim;
numElements = argv[0]->value.arr->n_elts;

/*convert the array to double*/
vpTmp = IDL_CvtDbl(1, &(argv[0]));
pbOutArray = (double*)vpTmp->value.arr->data;
for (i = 0; i < numElements; i++)
{
pbOutArray[i] = 11.0;
}
if (vpTmp != argv[0])
{
IDL_VarCopy(vpTmp, argv[0]);
}
}


第四步:修改DLM文件为:

MODULE IDLtoC
DESCRIPTION example programs IDL to C
VERSION 1.0
SOURCE DuanYaxin
BUILD_DATE April 2016
FUNCTION IDLTOC_SINGLEINT 1 1
FUNCTION IDLTOC_FINALSCALAR 4 4
FUNCTION IDLTOC_SINGLEINTARRAY 1 1
PROCEDURE IDLTOC_DOUBLEINT 2 2
PROCEDURE IDLTOC_ARRAYINPLACE 1 1


第五步:编译,运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IDL