Recent

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

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
How to pass pascal string to c function expecting char const *
« on: February 27, 2017, 04:41:54 pm »
I'm trying to display a (variable) array of strings using the Allegro library by calling al_draw_text(...) but it gives me an assertion failure.

Looked at the source of text.c on github and it expects char const* as it's last parameter - what's required, an array of an array of PChar?

TIA

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11458
  • FPC developer.
Re: How to pass pascal string to c function expecting char const *
« Reply #1 on: February 27, 2017, 05:36:02 pm »
a pchar or a ppchar, though declaring an array of strings that way  is a bit old school.

If it is supposed to be multiple values and there is no separate parameter to pass a count, then the last entry in the array of pchars that the ppchar points to must be zero.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #2 on: February 27, 2017, 06:16:30 pm »
I'm trying to display a (variable) array of strings using the Allegro library by calling al_draw_text(...) but it gives me an assertion failure.

Looked at the source of text.c on github and it expects char const* as it's last parameter - what's required, an array of an array of PChar?
i'm not familiar with allegro so in case wrong i apologize.

According to online documentation of al_draw_text:
Quote
Writes the 0-terminated string text onto bmp at position x, y, using the specified font

afaik, that means no array of string but just _a_ nul terminated string (which is a PChar when using c).

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: How to pass pascal string to c function expecting char const *
« Reply #3 on: February 27, 2017, 07:05:48 pm »
Thanks both.

If I define the array like this:

Code: [Select]
textmessage: array[1..NUMMESSAGES] of array of Pchar;

I can assign like this:
Code: [Select]
textmessage[5] := 'Hello';

but I still get assertion fail at this line:
Code: [Select]
al_draw_text(font, al_map_rgb_f (0, 1, 1), 550, i * 16, 0, textMessage[i]);

I'm guessing I might need an ugly old pointer ( just the sort of thing I was hoping to avoid) - but how?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #4 on: February 27, 2017, 07:25:03 pm »
Code: [Select]
textmessage: array[1..NUMMESSAGES] of array of Pchar;
Try:
Code: [Select]
textmessage: array[1..NUMMESSAGES] of Pchar;
and see if that helps

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: How to pass pascal string to c function expecting char const *
« Reply #5 on: February 27, 2017, 07:43:18 pm »
char const* in C is just const PChar in Pascal. The const semantic is even equivalent in FPC (it's a promise from the function writer that this parameter will not be modified inside the function body).

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: How to pass pascal string to c function expecting char const *
« Reply #6 on: February 27, 2017, 08:08:34 pm »
Try:
Code: [Select]
textmessage: array[1..NUMMESSAGES] of Pchar;
and see if that helps

I beg your pardon, that's what I actually had in my program (not array of array,  I just typed it wrong here) and it doesn't work. All the operations I carry out in Pascal work as expected when defined in this way but it still fails when I call the allegro routine.

char const* in C is just const PChar in Pascal. The const semantic is even equivalent in FPC (it's a promise from the function writer that this parameter will not be modified inside the function body).

Sorry, I don't quite understand, are you saying that I need to define the array as const?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #7 on: February 27, 2017, 08:15:09 pm »
I beg your pardon, that's what I actually had in my program (not array of array,  I just typed it wrong here) and it doesn't work. All the operations I carry out in Pascal work as expected when defined in this way but it still fails when I call the allegro routine.
Using array index starting with one... i can almost feel your pain. Almost...  :D

Point being:
Code: [Select]
al_draw_text(font, al_map_rgb_f (0, 1, 1), 550, i * 16, 0, textMessage[i]);
Don't do that, but instead:
Code: [Select]
al_draw_text(font, al_map_rgb_f (0, 1, 1), 550, i * 16, 0, textMessage[5]);
Note the five.

If that works then al_draw_text() is not at fault but instead your code is.
« Last Edit: February 27, 2017, 08:23:52 pm by molly »

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: How to pass pascal string to c function expecting char const *
« Reply #8 on: February 27, 2017, 09:52:03 pm »
If that works then al_draw_text() is not at fault but instead your code is.

Hmm. Here's all my code that concerns textMessage, it's not referenced anywhere else:

definition:
Code: [Select]
var
textMessage: array[1..NUMMESSAGES] of pchar;

I have good reason for using a 1 based rather than zero-based array. NUMMESSAGES is a const.

a single assignment:
Code: [Select]
addMessage('Hello');

Procedure to clear all messages:
Code: [Select]
procedure clearMessages();
var
i: integer;
begin
for i := 1 to NUMMESSAGES do
textMessage[i] := '';
end;

Add a message:
Code: [Select]
procedure addMessage(m: pchar);
var
i: integer;
begin
for i := 2 to NUMMESSAGES do
textMessage[i-1] := textMessage[i];
textMessage[NUMMESSAGES] := m;
end;

and the code to draw the messages:
Code: [Select]
procedure renderMessages();
var
i: integer;
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]);
end;
end;

But I get '/build/allegro5-NKtrUL/allegro5-5.2.2/addons/font/text.c:107: al_draw_text: Assertion `text' failed.'

From the definition in the C code on github:
Code: [Select]
void al_draw_text(const ALLEGRO_FONT *font,   ALLEGRO_COLOR color, float x, float y, int flags, char const *text)
.

According to http://www.freepascal.org/docs-html/ref/refsu13.html, the result of using var pchar has the same effect as const pchar

I can't see what's wrong.  :-\

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #9 on: February 27, 2017, 09:57:24 pm »
I can't see what's wrong.  :-\
Try declaring your strings as being ansistring.

For some odd reason the allegro 5.2 alpha headers defined it as such. That is, assuming that ansistring type was not overridden somewhere else in the allegro headers. In case it did, then use type AL_STR for your strings.

fwiw: sorry for the confusion. initially i used the online documentation as guidance.

ps: PChars work for me as well. No idea what goes wrong in your code. Have you looked at the font demo example ?
« Last Edit: February 27, 2017, 10:13:01 pm by molly »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: How to pass pascal string to c function expecting char const *
« Reply #10 on: February 28, 2017, 05:05:35 am »
Sorry, I don't quite understand, are you saying that I need to define the array as const?
No, that point is no matter where it comes from (an array element, a record field, etc.), the final type of value you pass must be PChar. You can simply ignore the const if you don't understand.

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: How to pass pascal string to c function expecting char const *
« Reply #11 on: February 28, 2017, 09:41:17 am »
I can't see what's wrong.  :-\
Try declaring your strings as being ansistring.

For some odd reason the allegro 5.2 alpha headers defined it as such. That is, assuming that ansistring type was not overridden somewhere else in the allegro headers. In case it did, then use type AL_STR for your strings.

fwiw: sorry for the confusion. initially i used the online documentation as guidance.

ps: PChars work for me as well. No idea what goes wrong in your code. Have you looked at the font demo example ?

AL_STR gives me 'identifier not found' error, even tough I seem to have all the necessary units in the uses clause. All the al_draw_text calls in the allegro.pas examples use literal strings, eg:

Code: [Select]
al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, 'red');

Whether I use {$H+} for ansistrings in the unit in which the string array is declared or the main program I still get the failed assertion.

Very confusing!

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #12 on: February 28, 2017, 10:03:53 am »
AL_STR gives me 'identifier not found' error, even tough I seem to have all the necessary units in the uses clause.
Type AL_STR is defined inside unit al5base.pas.

Just to be clear: i've downloaded the file allegro-pas.5.2.alpha-2-src-pas.zip from here.

Other than that i was lazy and
- extracted all the units from allegro-pas.5.2.alpha-2-src-pas.zip\allegro.pas\lib into the root of my project dir
- extracted the files common.pas and ex_font.pas from allegro-pas.5.2.alpha-2-src-pas.zip\allegro.pas\examples into that same directory
- extracted the directory allegro-pas.5.2.alpha-2-src-pas.zip\allegro.pas\bin\examples\data to the same directory (directory data has become a subdir of my project dir, with all data files located inside there).
- Extracted the binary package from allegro website, so that all dll files are inside my project directory (observant readers might attack me right now -> sue me for using a VM)

Quote
All the al_draw_text calls in the allegro.pas examples use literal strings, eg:

Code: [Select]
al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, 'red');
Well, it takes about 5 iseconds to add a variable named reddish typed as PChar and add the text 'reddish' to that just before doing that call and replace
Code: [Select]
al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, 'red');
with
Code: [Select]
al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, reddish);

Quote
Whether I use {$H+} for ansistrings in the unit in which the string array is declared or the main program I still get the failed assertion.
I have not changed anything else inside the original ex_font.pas example code.... ok ok ok. if you look at the attached picture you caught me of a little lie  :-X

Quote
Very confusing!
It's getting confusing for me as well now (*). All i can tell you right now that it works for me doing it such a lazy unfashionable manner.

Of course in a more fashioned manner you would have to place the allegro units somewhere more appropriate and make sure fpc is able to locate those units but, other then that it should not matter much.

(*) please state the target for which you are compiling, which version of FPC you are using (and version of lazarus in case using lazarus as well)
As an additional bonus, post the output you get from invoking "fpc -B -va ex_font.pas" from the command-line. The compiler i very good at telling what is wrong albeit it takes the compiler a few lines to make some definitive conclusion. (you can pipe it to a file, using: "fpc -B -va ex_font.pas >mylogfile.txt"
« Last Edit: February 28, 2017, 10:36:05 am by molly »

mig-31

  • Sr. Member
  • ****
  • Posts: 305
Re: How to pass pascal string to c function expecting char const *
« Reply #13 on: February 28, 2017, 10:16:00 am »
Swith to use ansistring {$H+}
Code: Pascal  [Select][+][-]
  1.    var
  2.       str:string[255];
  3.    begin
  4.       al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, @str[1]);
  5.      
  6.    end;
  7.  

Lazarus 2.2.6 - OpenSuse Leap 15.4, Mageia 8, CentOS 7

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to pass pascal string to c function expecting char const *
« Reply #14 on: February 28, 2017, 10:21:01 am »
Swith to use ansistring {$H+}
Code: Pascal  [Select][+][-]
  1.    var
  2.       str:string[255];
  3.    begin
  4.       al_draw_text (f1, al_map_rgb (255, 0, 0), 10, 10, 0, @str[1]);
  5.      
  6.    end;
  7.  
Sorry mig-31 but, either i am confused or you seem to be ;D

{$H+} = turns on ansistrings, yes.

Not exactly needed because allegro is being very specific with using types but, i grant you that,

But then ?
Code: [Select]
   var
      str:string[255];
Which declares a shortstring, thereby going against the $H+ switch ?

why is that exactly ?

shortstrings are not zero terminated afaik while ansistrings are.

As can been seen from my example, using AnsiString, PChar and AL_STR type all work (because of the way ansistrings are implemented in FPC).

Terminating the shortstring with zero manually i would not consider a workable solution.
« Last Edit: February 28, 2017, 10:39:27 am by molly »

 

TinyPortal © 2005-2018