Page 2 of 2

Help with mixing C and C++ code

Posted: Tue Nov 07, 2023 2:42 am
by mberryman
Ok, I'm stumped. What is the syntax that would allow a C++ routine to call a C routine that is using 32-bit pointers? The following illustrates the issue I am trying to resolve:

Code: Select all

$ type test.cxx
extern "C" {
extern int load_defaults(const char *conf_file, const char **groups,
                       int *argc, __char32_t ***argv);
}

static const char *load_default_groups[]=
{ "mysqladmin", "client", "client-server", "client-mariadb", 0 };

int main(int argc,char *argv[])
{

        int x = load_defaults("my",load_default_groups,&argc,&argv);

}
$ cxx test
test.cxx;1:12:10: error: no matching function for call to 'load_defaults'
        int x = load_defaults("my",load_default_groups,&argc,&argv);
                ^~~~~~~~~~~~~
test.cxx;1:2:12: note: candidate function not viable: no known conversion from 'char * __ptr32 **' to 'char32_t ***' for 4th argument
extern int load_defaults(const char *conf_file, const char **groups,
           ^
1 error generated.
$
Also, what is the magic incantation that would grant a C++ routine access to fmod and exp2?

Code: Select all

$ cxx/version
clang version 10.0.1 (git@bitbucket.org:vms_software/llvm-10.0.1.git b2ed69f05fb4239b21b6ff2f806caaf4691c9719)
Build date: 09-19-2023
Target: x86_64-OpenVMS
Thread model: posix
InstalledDir: $1$DGA3:[SYS0.SYSCOMMON.][SYSEXE]

Re: Help with mixing C and C++ code

Posted: Thu Nov 09, 2023 1:58 am
by mberryman
I thought I would try compiling just the client portion with /POINTER=64=ARGV in order to eliminate the issue with the different pointer sizes. The compilation went fine but, on x86, the result couldn't parse the command line; whereas, on IA64 using the exact same build process, it could parse the command line just fine. I couldn't test on Alpha because Alpha doesn't support a 64-bit argv.

This result causes me to believe we are still looking at compiler bugs.

Re: Help with mixing C and C++ code

Posted: Sun Mar 17, 2024 8:07 am
by soutbarr
Your issue is how the C compiler is naming functions.

#include <stdio.h>

int load_defaults(const char *conf_file, const char **groups, int *argc, void
*argv)
{
char **argv2;
argv2 = (char**)argv;
for(int i = 0; i < *argc; i++)
{
printf("%s\n", argv2);
}
printf("HI I'm the C routine\n");
return 1;
}

There's the C code, when it compiles it is exported in the .obj file as LOAD_DEFAULTS all caps

#include <iostream>

extern "C"
{
extern int LOAD_DEFAULTS(const char *conf_file, const char **groups, int *argc,
void *argv);
}

static const char *load_default_groups[]=
{ "mysqladmin", "client", "client-server", "client-mariadb", 0 };

int main(int argc, char *argv[])
{
int x = LOAD_DEFAULTS("my",load_default_groups,&argc,(void*)argv);
std::cout << x << std::endl;
}


There's the C++ code

Re: Help with mixing C and C++ code

Posted: Sun Mar 17, 2024 11:30 am
by sms

Code: Select all

> Your issue is how the C compiler is naming functions.
> [...]

   I wouldn't bet on that.

      help cc /names
      help cxx /names

Re: Help with mixing C and C++ code

Posted: Sun Mar 17, 2024 1:34 pm
by soutbarr
True, I went with the default naming schemes.
Apparently the order the files are linked matters too.
I name cross2.cxx and cross.c after compiling them both.

Code: Select all

cxx cross2.cxx
cc cross.c
link cross.obj,cross2.obj
run cross

Returns
HI I'm the C routine

link cross2.obj,cross.obj
run cross2

kitsu$dka0:[sys0.][sysmgr.cprogram]cross2.exe;41kitsu$dka0:[sys0.][sysmgr.cprogr
am]cross2.exe;4
HI I'm the C routine
1
It will execute the C routine from the C++ main.

Re: Help with mixing C and C++ code

Posted: Sun Mar 17, 2024 4:52 pm
by hb
Apparently the order the files are linked matters too.
This looks like a bug in the C++ compiler. The symbol for the "User transfer code address" in your C++ object module (ELF$TFRADR) is a weak symbol. If there is a "main" function/routine in an object module, this symbol should not be weak.

If the linker sees two such weak symbols, the first one wins and the winner is the "User transfer code address" .