* * *

Author Topic: How to pass pascal string to c function expecting char const *  (Read 2385 times)

mrguzgog

  • New member
  • *
  • Posts: 42
Re: How to pass pascal string to c function expecting char const *
« Reply #15 on: February 28, 2017, 11:47:54 am »
Swith to use ansistring {$H+}

Thanks for the suggestion but I tried that already (see my previous post), putting the directive at the top of the program and/or in the unit where the string array is declared.

@molly: The example compiles and runs as expected. If I change my procedure thus:
Code: [Select]
procedure renderMessages();
var
i: integer;
test2: array[1..10] of string;
begin
for i := 1 to NUMMESSAGES do
begin
//al_draw_text(font, al_map_rgb_f (0, 1, 1), 550, i * 16, 0, textMessage[i]);
test2[i] := 'array test';
al_draw_text(font, al_map_rgb_f (0, 1, 1), 550, i * 16, 0, test2[i]);
end;
end;

It works! I also changed the type of test2 to array of pchar and that works as well.

However, if I define 'test2' as an array of either type (string or pchar) in a different unit I get the same assertion fail. Bizarre.





Thaddy

  • Hero Member
  • *****
  • Posts: 3400
Re: How to pass pascal string to c function expecting char const *
« Reply #16 on: February 28, 2017, 11:52:03 am »
A C string (or C++) string type has a range of 1..255 and the length is determined by a #0.
We call it a PChar.
A pascal string can contain zero's. A C string can't.... Therefor that is unsafe. A C string is unsafe.
A Pascal string (H+ or H-) can be hardcast to a C string(PChar). The compiler adds the terminating zero('s).
If you are using a Pascal string type to interface with C (family) code, just hardcast it.

Therefor you also should not declare such a string as string[255] but simply as string and hard cast to PChar.
C people are rather stupid, they determine length by the #0 every time with strlen etc. (so they need to read every byte before they know what the length is...)
Pascal people are smarter: they store the length of the string as a negative offset of the memory occupied by the string. So we know the length with a single read of the length field.

Just cast the string, any string, to PChar and usually it's ok.
The exception is that Pascal users tend to expect that a #0 can be anywhere in between.

So C? Hardcast!
« Last Edit: February 28, 2017, 11:55:34 am by Thaddy »

mrguzgog

  • New member
  • *
  • Posts: 42
Re: How to pass pascal string to c function expecting char const *
« Reply #17 on: February 28, 2017, 12:31:50 pm »
Thanks Thaddy. However, I don't see why the assertion only fails when the array is defined in another unit.

I'm not using Delphi mode, so according to this thread[1] I have short strings that require extra work to cast as pchar  so I can't just do pchar(textMessage). It's all getting a bit messy  :(


[1]http://forum.lazarus.freepascal.org/index.php?topic=14972.0

Thaddy

  • Hero Member
  • *****
  • Posts: 3400
Re: How to pass pascal string to c function expecting char const *
« Reply #18 on: February 28, 2017, 12:55:25 pm »
It's not messy at all. A hard cast will add the terminating zero.

mrguzgog

  • New member
  • *
  • Posts: 42
Re: How to pass pascal string to c function expecting char const *
« Reply #19 on: February 28, 2017, 01:05:37 pm »
OK, I've finally got it working with an array of pchar when defined in a different unit - it seems that

Code: [Select]
test2[i] := '';

is not acceptable initialisation for a pchar which is why it was crashing out. Thanks all for you help.

molly

  • Hero Member
  • *****
  • Posts: 1559
Re: How to pass pascal string to c function expecting char const *
« Reply #20 on: February 28, 2017, 01:14:27 pm »
The header declaration of this function (amongst others) reads:

Code: [Select]
PROCEDURE al_draw_text (CONST font: ALLEGRO_FONTptr; color: ALLEGRO_COLOR; x, y: AL_FLOAT; flags: AL_INT; CONST str: AL_STR);
    CDECL; EXTERNAL ALLEGRO_FONT_LIB_NAME;

Where AL_STR is defined as:
Code: [Select]
AL_STR = ANSISTRING;

So, afaik that basically means: whatever i throw at that function, be it a ShortString, a PChar or a AnsiString and to an certain extend even unicodestring, (with conversion loss as expressed by the compiler) that the compiler takes care of making sure that whatever is passed it will be pushed to the library as an AnsiString ?

That still does not explain any of TS issues...

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 577
    • Burdjia
Re: How to pass pascal string to c function expecting char const *
« Reply #21 on: March 05, 2017, 08:37:40 pm »
Sorry for the late response but here I am finally.

If you're using Allegro with Pascal you should use Allegro.pas, so you don't need to deal with such stuff as "how to pass this to a C function" because Allegro.pas will do it correctly.

Except if you're doing some weird stuff.  Are your doing weird stuff?  You shouldn't.

The header declaration of this function (amongst others) reads:

Code: [Select]
PROCEDURE al_draw_text (CONST font: ALLEGRO_FONTptr; color: ALLEGRO_COLOR; x, y: AL_FLOAT; flags: AL_INT; CONST str: AL_STR);
    CDECL; EXTERNAL ALLEGRO_FONT_LIB_NAME;

Where AL_STR is defined as:
Code: [Select]
AL_STR = ANSISTRING;

So, afaik that basically means: whatever i throw at that function, be it a ShortString, a PChar or a AnsiString and to an certain extend even unicodestring, (with conversion loss as expressed by the compiler) that the compiler takes care of making sure that whatever is passed it will be pushed to the library as an AnsiString ?
Yes, it is.

I know there's a problem with text encoding.  That's the main reason I didn't release a "beta" version.  Anyway, I used both ASCII and UTF-8 enconding in ANSISTRING variables with Allegro.pas 5.2.alpha and seems to work.  See my TINS'16 entry, it includes a few UNICODE text (UTF-8) and renders it correctly even using a TTF font.

[Edit]

I was reading the thread again so I'll add something:

As well you're using ANSISTRING (i.e. {H+} or -Sh) you should not have any problem to use texts on Allegro, even using UNICODE encoding (but you may need to configure Allegro).  I use this always with UTF-8 strings without any problem.

If you're using SHORTSTRING you need to convert them to ANSISTRING (i.e. use the functions and procedures of the "strutils" unit.  Anyway I don't understand why you may want to do so.

If you're doing something weird (i.e. WIDESTRING?) then you can change the AL_STR and AL_STRptr definitions if you need it.

In any case, if you find something interesting, please let me know so I can improve Allegro.pas to make it better.
« Last Edit: March 05, 2017, 08:51:59 pm by Ñuño_Martínez »

mrguzgog

  • New member
  • *
  • Posts: 42
Re: How to pass pascal string to c function expecting char const *
« Reply #22 on: March 10, 2017, 06:48:34 pm »
Ñuño: Thanks for the reply, that info will be useful.

And a BIG thanks for allegro.pas, it's great!  :)

An unrelated issue: I have a tiny issue with one of the examples: ex_mouse exits immediately after drawing the screen, when I get 5 minutes I'll try to track down the problem (unless you already know of it?)

Paul.

EDIT: Couldn't resist a quick look at ex_mouse. The problem is the test in the repeat/until block. If I replace:

Code: [Select]
UNTIL al_key_down (KbdState, ALLEGRO_KEY_ESCAPE)

with a 'forever' condition (eg UNTIL (1=0) ) it works as expected. I haven't looked into al_key_down() yet so I'm not sure what's going on there.


« Last Edit: March 10, 2017, 07:03:25 pm by mrguzgog »

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 577
    • Burdjia
Re: How to pass pascal string to c function expecting char const *
« Reply #23 on: March 11, 2017, 06:50:22 pm »
And a BIG thanks for allegro.pas, it's great!  :)
Thanks.  :-[  May be you want to join the Pascal Game Development forum. They don't use Allegro.pas a lot but...

About the problem with the mouse example, I know there are a few issues related with the keyboard state.  I've almost finished my (alpha version) game engine so may be I can spend a few time with that and see if it can be fixed.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus