Hi Diego,
There are problems with your code -- some are actual bugs that are 
causing the program to fail, and others are just things I do differently 
for the sake of readability or maintainability.
READABIITY/MAINTAINABILITY
a) I'd put your iconv-related stuff into a copy book so you can easily 
re-use it.
b) Instead of repeating the structure in the toCde and frmCde data 
structures, and coding the name of the structure in every subfield, I'd 
create one QUALIFIED data structure named QtqCode_t (since that's what 
IBM calls it) and use LIKEDS to create toCde and frmCde.
c) Instead of passing pointers to QtqIconvOpen(), I'd simply pass the 
LIKEDS data structures to it.  These can be CONST.
d) You're actually calling the QtqIconvOpen() API, but you've renamed 
your prototype (via extproc) to be called iconv_open() which is the name 
of a different API on the system with a different syntax.  This is 
confusing.
ACTUAL ERRORS
a) You're passing the pInBuf, inBytesLft, pOutBuf and outBytesLft 
parameters to iconv() has CONST.  This is wrong -- the API is expected 
to change all of these variables.
b) You've put a variant character at the beginning of your __errno() 
prototype.  I used to make the same mistake!  This causes problems any 
time you try to send your code to someone who uses a different character 
set than you do.  For example, when you send your code to me, there's a 
garbage character at the beginning of the prototype, thus making it 
unusable.  Nowadays, I use the name 'sys_errno' instead of '@__errno' so 
that the code has no translation problems.
c) You aren't checking the return value from iconv().  You should only 
check the value of errno if it tells you that it failed.
d) You also aren't checking that QtqIconvOpen() was successful, but are 
proceeding to do translations... that'll make it awfully difficult to 
tell what the error is if QtqIconvOpen() fails.
e) You are passing %addr() and %size() to iconv().  iconv() wants to be 
able to change those values -- it can't change %addr() or %size() 
(actually -- it can, and it will -- becuase RPG will put the results of 
those functions in temporary memory locations -- but you'll be unable to 
read the changes it makes)
f) You are passing the same pointer and length for both the input and 
output buffer.  This will be problematic if you ever need to work with 
character sets that aren't purely single-byte (such as Unicode)
g) Iconv() will translate one character at a time from your buffer. 
Each time it succeeds in translating a character, it changes the input 
buffer pointer to be one higher (moving to th enext character).  It also 
changes the output buffer pointer to be one higher (moving to th enext 
character).  It also decreases the lengths of the two buffers, showing 
how much space is left after the translation.  The problem here is that 
you're passing pData directly to iconv() -- whcih changes the pointer 
that you called %alloc() with.  Becuase of this, there will be no way to 
deallocate the memory you got with %alloc since the pointer has changed. 
 You need to save the original pointer from %Alloc() in order to 
dealloc later.
h) Which brings me to:   your code doesn't even attempt to deallocate 
the buffer.
i) The iconv() API (for the reasons explained in g, above) wants a 
pointer to  pointer for each buffer.  The idea is that it needs a 
pointer to your pointer in order to change it.   Unfortunately, you're 
going one step further and passing a pointer to a pointer to a pointer.
A pointer is a variable that stores the address of data. So if you were 
trying to translate a variable, you'd do %addr(var) because that gives 
you the address of the variable.  However, you don't want to do 
%addr(pointer) because that doesn't give you the address of the data 
it's pointing to -- it gives you the address of the pointer itself.  You 
don't want to translate the MEMORY ADDRESS to ASCII -- you want to 
translate the data that it points to to ASCII!
Whew.
diego acevedo wrote:
Hi everybody:
  I'm writing a program that needs to convert a huge set of data (more than 64k) using RPGLE. 
   
  As you know, the maximun size allowed to declared a character field in this language is 65535 bytes (aka: 64k), but in this case, the data to send is more large (about 128k) Since the QDCXLATE can't be perform conversions above 32k's, I decided to use the iconv() API passing, as buffer, a pointer instead of a character field.
   
  The problem is that, when I pass a character field (no matter size) the funcion works wonderfully but, if I use a pointer (or pointer to pointer as the prototype says) no conversion is performed and the error returned is EBADF ("Descriptor not valid")
   
  Could anybody help me to solve this problem?
  Thank you very much!
   
  Diego
   
As an Amazon Associate we earn from qualifying purchases.