bmx-ng / bcc

A next-generation bcc parser for BlitzMax
zlib License
33 stars 13 forks source link

Error with "Struct" in external function definition: Syntax error - expecting ','. #627

Open GWRon opened 1 year ago

GWRon commented 1 year ago

Use the following files: test.bmx:

SuperStrict
Framework brl.standardio

Import "aud.bmx"

Print "here"

aud.bmx:

SuperStrict 
Framework brl.basic 

Import "external.h"
Extern 
    Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"
    Function test:Byte Ptr() = "char* test()"
EndExtern

external.h:

#include <stddef.h>
#include <stdint.h>
struct mystruct {
  size_t something;
};

int test_struct(struct mystruct *f, int chan);
static struct mystruct myfa={0};
char* test()
{ return &myfa; }

int test_struct(struct mystruct *fa, int chan) {
  return 0;
}

(readymade zip: imp_test.zip )

Output:

[  9%] Processing:aud.bmx
[ 10%] Processing:test.bmx
Compile Error: Syntax error - expecting ','.
[/imp_test/.bmx/aud.bmx.release.linux.x64.i;4;0]
Compilation failed.
GWRon commented 1 year ago

Changing above to:

test.bmx:

SuperStrict
Framework brl.standardio

Import "aud.bmx"

Extern 
    Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"
    Function test:Byte Ptr() = "char* test()"
EndExtern
Print "here"

aud.bmx:

SuperStrict 
Framework brl.basic 

Import "external.h"

so defining in test.bmx but importing header in the import file

Attention: "GW" (who reported that issue at discord) uses "Framework brl.basic" in the import file.

This leads to:

[100%] Linking:test
/usr/bin/ld: /imp_test/.bmx/aud.bmx.release.linux.x64.o: in function `test':
aud.bmx.release.linux.x64.c:(.text+0x0): multiple definition of `test'; /imp_test/.bmx/test.bmx.console.release.linux.x64.o:test.bmx.console.release.linux.x64.c:(.text+0x0): first defined here
/usr/bin/ld: /imp_test/.bmx/aud.bmx.release.linux.x64.o: in function `test_struct':
aud.bmx.release.linux.x64.c:(.text+0x10): multiple definition of `test_struct'; /imp_test/.bmx/test.bmx.console.release.linux.x64.o:test.bmx.console.release.linux.x64.c:(.text+0x10): first defined here
/usr/bin/ld: /imp_test/.bmx/aud.bmx.release.linux.x64.o: in function `_bb_imp_test_win_aud':
aud.bmx.release.linux.x64.c:(.text+0x57): undefined reference to `__bb_brl_basic_basic'
Compilation failed.

(the duplicate defs could be ... fiddled with by using an ifdef... yet I wonder why it is imported twice).

Removing the framework leads to just the duplicate def one - but it "compiled" in the sense of not throwing Compile Error: Syntax error - expecting ','.

and finally: test.bmx

SuperStrict
Framework brl.standardio

Import "external.h"

Extern 
    Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"
    Function test:Byte Ptr() = "char* test()"
EndExtern
Print "here"

outputs:

here
GWRon commented 1 year ago

If you comment out Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"

So:

Extern 
    'Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"
    Function test:Byte Ptr() = "char* test()"
EndExtern

it will compile too. So it stumbles only over the "struct" part of the external function declaration. But - as proven - it only stumbles (over "struct") when using in an "imported" file rather than the main file.

GWRon commented 1 year ago

wrapping the external.h stuff in "ifndef" to avoid duplicate definitions ...

external.h:

#include <stddef.h>
#include <stdint.h>
#ifndef EXTERNAL_H
#define EXTERNAL_H
struct mystruct {
  size_t something;
};

int test_struct(struct mystruct *f, int chan);
static struct mystruct myfa={0};
char* test()
{ return &myfa; }

int test_struct(struct mystruct *fa, int chan) {
  return 0;
}
#endif

disabling the "problematic external function definition" (also removing the framework command - as it adds another error/warning):

aud.bmx

SuperStrict 
'Framework brl.basic 

Import "external.h"

Extern 
'   Function test_struct:Int(f:Byte Ptr, chan:Int) = "int test_struct(struct mystruct*, int)"
    Function test:Byte Ptr() = "char* test()"
EndExtern

and keeping test.bmx the same:

SuperStrict
Framework brl.standardio

Import "aud.bmx"

rem
Import "external.h"

Print "here"

still outputs:

./bmk makeapp -g x64 -t console -a -r -x "/imp_test/test.bmx" (in directory: /BlitzMaxNG/bin)
[  9%] Processing:aud.bmx
[ 10%] Processing:test.bmx
[ 90%] Compiling:aud.bmx.release.linux.x64.c
[ 91%] Compiling:test.bmx.console.release.linux.x64.c
[100%] Linking:test
/usr/bin/ld: /imp_test/.bmx/aud.bmx.release.linux.x64.o: in function `test':
aud.bmx.release.linux.x64.c:(.text+0x0): multiple definition of `test'; /imp_test/.bmx/test.bmx.console.release.linux.x64.o:test.bmx.console.release.linux.x64.c:(.text+0x0): first defined here
/usr/bin/ld: /imp_test/.bmx/aud.bmx.release.linux.x64.o: in function `test_struct':
aud.bmx.release.linux.x64.c:(.text+0x10): multiple definition of `test_struct'; /imp_test/.bmx/test.bmx.console.release.linux.x64.o:test.bmx.console.release.linux.x64.c:(.text+0x10): first defined here
Compilation failed.
collect2: error: ld returned 1 exit status
Build Error: Failed to link /imp_test/test
woollybah commented 1 year ago

Parser probably isn't expecting "struct" there in struct mystruct* within = "int test_struct(struct mystruct*, int)"