Link object files from VC++ and GCC?

R

Rick C. Hodgin

Is there a way to link object files between Visual C++ and GCC?

I have some data that I need to encode like this:
char* list[] = {
"one",
"two",
"three",
};

Unfortunately, by default, the list[0], list[1], and list[2] pointers point
to data that's in read-only memory. Any attempt to do something like
memcpy(list[0], "eno", 3) fails with "Access Violation" on Windows.

So, I discovered this syntax in GCC which creates the elements in read-write
memory, allowing memcpy(list[0], "eno", 3) to work properly:
char* list[] = {
(char []) { "one" },
(char []) { "two" },
(char []) { "three" },
};

I need the data pointed to by those list elements to be read-write in my
application. I can use this compound literal syntax in GCC to create
them in read-write memory, and it works in GCC. However, Visual C++
does not support this compound literal syntax and generates about 5
errors per line when I attempt it. :)

I was wondering if there's a way to link in that one file, which will
contain nothing more than a list like this sample, but with about 100
separate elements in it representing a source code file I need to
modify somewhat at use (replacing placeholders like "[9999]" with the
actual runtime observed values, such as "[ 1]" and so on), to my
Visual C++ generated code in Visual Studio 2008?

I'm looking for something like this:
gcc -c my_list.c
cl /c my_prog.cpp
link my_list.o my_prog.obj my_prog.exe

Thank you in advance.

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

In the alternative, does anyone know of a version of a Windows-based C/C++
compiler that will honor the compound literal syntax, which will link in
with the correct object format?

Best regards,
Rick C. Hodgin
 
A

Alf P. Steinbach

Is there a way to link object files between Visual C++ and GCC?

I have some data that I need to encode like this:
char* list[] = {
"one",
"two",
"three",
};

Unfortunately, by default, the list[0], list[1], and list[2] pointers point
to data that's in read-only memory. Any attempt to do something like
memcpy(list[0], "eno", 3) fails with "Access Violation" on Windows.

So, I discovered this syntax in GCC which creates the elements in read-write
memory, allowing memcpy(list[0], "eno", 3) to work properly:
char* list[] = {
(char []) { "one" },
(char []) { "two" },
(char []) { "three" },
};

I need the data pointed to by those list elements to be read-write in my
application. I can use this compound literal syntax in GCC to create
them in read-write memory, and it works in GCC. However, Visual C++
does not support this compound literal syntax and generates about 5
errors per line when I attempt it. :)

I was wondering if there's a way to link in that one file, which will
contain nothing more than a list like this sample, but with about 100
separate elements in it representing a source code file I need to
modify somewhat at use (replacing placeholders like "[9999]" with the
actual runtime observed values, such as "[ 1]" and so on), to my
Visual C++ generated code in Visual Studio 2008?

I'm looking for something like this:
gcc -c my_list.c
cl /c my_prog.cpp
link my_list.o my_prog.obj my_prog.exe

Should work, if you get the name mangling compatible. Since both
compilers use COFF format. But you're barking up the wrong tree: it
doesn't make sense to do this.

First of all you don't need the data to be read/write.

Secondly, if you did need the data to be read/write (which you don't)
it's trivial to specify that:

char item_0[] = "one";

and so on, as long item_0 is static.

Cheers & hth.,

- Alf
 
V

Victor Bazarov

In the alternative, does anyone know of a version of a Windows-based C/C++
compiler that will honor the compound literal syntax, which will link in
with the correct object format?

Why not just use implementation-specific feature in VC++ to place your
data in the read-write memory and go for const-casting it before trying
to change? That's easier than linking GCC obj files with VC++ ones.

You also could simply declare your 'list' as an array of arrays instead
of the array of pointers. That would just as well allow you to edit
those elements:

char list[][10] = { "one", "two", "three" };

It's been a while I used straight chars, though, take it with a grain of
salt. Alternatively, use 'std::string':

std::string list[] = { "one", "two", "three" };
...
list[0]= "eno";

and forget about memcpy...

V
 
R

Rick C. Hodgin

I have a data portion that is a source file that changes from time to time.
It is about 100 lines long. I include that in the source file to be written
out to the output file. It contains portions like this (greatly simplified
for this example):

char* sourceCode[] = {
"if (thisThing.someOtherThing[9999].function())\r\n",
"{\r\n",
" // Do something\r\n",
"} else {\r\n",
" // Do something else\r\n",
"}\r\n"
};

The actual code is in another language and contains several references to
the "[9999]" portion, which I swap out with an iterative value at runtime.
I currently have 812 instances where this is generated and they increment
accordingly. I have a "macro" routine that searches for [ and ] on the
same line with 4 characters between them, and then updates the value within
using something like sprintf(line[n] + location, "%4u", iterativeValue);.

I have considered doing it like this:

char sourceCode[] =
"if (thisThing.someOtherThing[9999].function())\r\n"
"{\r\n"
" // Do something\r\n"
"} else {\r\n"
" // Do something else\r\n"
"}\r\n";

And having a read-write value that way, but there are some goals of future
expansion where there will be more than one replacement done within. So,
I wanted it line-by-line so I could tag on a prefix on each line indicating
the type of value that should be there, and so on.

The workaround I'm using right now is to add something like this at startup:

char* sourceCode[] = {
"if (thisThing.someOtherThing[9999].function())\r\n",
"{\r\n",
" // Do something\r\n",
"} else {\r\n",
" // Do something else\r\n",
"}\r\n",
null
};

for (int i = 0; list; i++)
list[0] = strdup(list[0]);

In that way, everything is read-write. But, with the compound literal
syntax I don't need to do anything at startup, and can simply create
read-write variables at compile-time, which are then directly usable
at runtime. I made a macro to do this:

#define RW(x) (char []) { x }

char* sourceCode[] = {
RW("if (thisThing.someOtherThing[9999].function())\r\n"),
RW("{\r\n"),
RW(" // Do something\r\n"),
RW("} else {\r\n"),
RW(" // Do something else\r\n"),
RW("}\r\n"),
null
};

Now the compiler does all the work for me, and I just use the read-write
strings auto-populated for me at startup.

No, I don't need to do it this way. There are a few design decisions
which have factored in to me doing it this way.

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

Should be:

for (int i = 0; list; i++)
list = strdup(list);

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

COFF output in GCC was the key. I was able to get it working.

Here's are the steps for a sample build:

(1) Install MinGW on Windows with GCC and bases.
(2) Create the two source files below.
(3) Launch a command prompt that has the path for visual studio tools.
(4) Execute these steps:
(a) C:\>PATH=%PATH%;c:\mingw\bin\
(b) C:\>g++ -c -gcoff list.cpp -o list.obj
(c) C:\>cl /c main.cpp
(d) C:\>link main.obj list.obj /OUT:main.exe
(e) C:\>main
!ne
!wo
!three
(f) C:\>_


=========list.cpp========
#define RW(x) (char []) { x }

extern "C"
{

char* list[] =
{
RW("one"),
RW("two"),
RW("three")
};

}
===========END===========


=========main.cpp========
#include <stdlib.h>
#include <stdio.h>

extern "C"
{
extern char* list[];
}

int main(int argc, char* argv[])
{
for (int i = 0; list; i++)
{
list[0] = '!'; // Prove it's read-write
puts(list); // Show it
}
}
===========END===========

G++ and CL working hand-in-hand. :)

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

Why not just use implementation-specific feature in VC++ to place your
data in the read-write memory and go for const-casting it before trying
to change? That's easier than linking GCC obj files with VC++ ones.

Such as?
You also could simply declare your 'list' as an array of arrays instead
of the array of pointers. That would just as well allow you to edit
those elements:
char list[][10] = { "one", "two", "three" };

This option was discussed, but it is wasteful. As I say the actual
implementation is about 100 lines of source code, some of which are 80+
characters long, most of which are 15 characters long.
It's been a while I used straight chars, though, take it with a grain of
salt. Alternatively, use 'std::string':
std::string list[] = { "one", "two", "three" };
...
list[0]= "eno";
and forget about memcpy...

I am currently working on developing my own C-like language that has some
elements of C and some of C++, called RDC (Rapid Development Compiler).
I will not support std::string in that language, along with many other C++
features, so I am not using them for that reason. I hope someday to migrate
all of my code to my own compiler.

Best regards,
Rick C. Hodgin
 
D

David Brown

In the alternative, does anyone know of a version of a Windows-based C/C++
compiler that will honor the compound literal syntax, which will link in
with the correct object format?

Yes, gcc runs fine on Windows. Download mingw. I believe it is even
possible to get VS to work with such "alien" compilers, but I don't know
how well it will handle modern C syntax highlighting.
 
H

Hans-Peter

"Rick C. Hodgin" wrote in message
Is there a way to link object files between Visual C++ and GCC?

I have some data that I need to encode like this:
char* list[] = {
"one",
"two",
"three",
};

Unfortunately, by default, the list[0], list[1], and list[2] pointers
point
to data that's in read-only memory. Any attempt to do something like
memcpy(list[0], "eno", 3) fails with "Access Violation" on Windows.

You can force that the list will be in the data segment by using #pragma
data_seg() but this will only move the pointer array in to the data segment.
Changing the strings to fixed size will do the job:

#pragma data_seg()
char list[3][6] = {
{ "one" },
{ "two" },
{ "three"}
};

BTW the compiler will throw an error if you set the array dimensions too
small.

Best regards
Hans-Peter
 
R

Rick C. Hodgin

"Rick C. Hodgin" wrote in message
Is there a way to link object files between Visual C++ and GCC?
I have some data that I need to encode like this:
char* list[] = {
"one",
"two",
"three",
};
Unfortunately, by default, the list[0], list[1], and list[2] pointers
point to data that's in read-only memory. Any attempt to do
something like memcpy(list[0], "eno", 3) fails with "Access Violation"
on Windows.

You can force that the list will be in the data segment by using #pragma
data_seg() but this will only move the pointer array in to the data segment.
Changing the strings to fixed size will do the job:
#pragma data_seg()
char list[3][6] = {
{ "one" },
{ "two" },
{ "three"}
};

BTW the compiler will throw an error if you set the array dimensions too
small.

Hans-Peter, thank you for your response. I had considered using the [6]
add-on. The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.

I like this new solution, as it not only allows me to do my simple list[]
thing, but also to use GCC and VC++ together.

FWIW, I'm not using the GCC/VC++ solution for my project. The original
solution I found is working just fine. :) This whole thing has been
more of a mental exercise to try to find an alternate course.

Best regards,
Rick C. Hodgin
 
V

Victor Bazarov

[..] The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.
[..]

Just curious, in what world a few hundred bytes is a waste of memory
worthy of consideration? Are you targetting an embedded system or a
legacy computer with 640K memory (last century technology)? Don't get
me wrong, please, it's just that I have often enough seen real
(significant) time wasted on finding a solution to save a few
microseconds or a few [hundred] bytes, that usually in the end cannot be
accounted for. I can understand when students do that in the course of
their studies, but I don't understand the need for it when creating a
product for others to consume.

V
 
R

Rick C. Hodgin

[..] The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.
[..]

Just curious, in what world a few hundred bytes is a waste of memory
worthy of consideration? Are you targetting an embedded system or a
legacy computer with 640K memory (last century technology)? Don't get
me wrong, please, it's just that I have often enough seen real
(significant) time wasted on finding a solution to save a few
microseconds or a few [hundred] bytes, that usually in the end cannot be
accounted for. I can understand when students do that in the course of
their studies, but I don't understand the need for it when creating a
product for others to consume.

I'm getting a lot of flack over this from many people on many lists. It's
like ... if I don't do it the way everybody else does then I'm the one who's
wrong. And because I look toward things which are important to me, and
because I choose to not waste memory where it doesn't need to be wasted,
while also simplifying the source code implementation of this task, that
it is somehow a bad choice.

FWIW, I had a working solution after getting the first access violation error
in the Visual Studio debugger and realizing why I got it. It took me a few
seconds to realize what was happening, even though it was unexpected. But,
the whole issue was one of those things I wanted to better understand. It
seemed (and still seems) a very silly imposition, that string literals
created in that way (as data pointed to in a read-write array) should always
be read-only unless they are explicitly cast through such a clunky syntax as
compound literals, a feature that not all C compilers even support.

It was a mental exercise as much as anything else, a pursuit of a question,
to satiate curiosity. I wound up not using the solution, but just
discovering and testing it out. I learned many things in the process, not
the least of which was how to integrate GCC and Visual C++ together in
harmony. That alone was worth all the time I spent on it.
I do not respond to top-posted replies, please don't ask

Just curious, in what world would you deny giving help to someone in need
simply because they top-posted? I had someone in 2011 or 2012 on the
Trisquel mailing list tell me that I was a top poster and that he
wasn't going to help me. I didn't even know what he was talking about
and had to ask what that phrase "top poster" meant. When I found out
I was floored that such a ridiculous barrier exists between the
help-seekers, and the knowledge-holders on a forum like this.

It really taught me something ... a concept that is so amazingly important
to only a select few, those who desire to divide people into groups of
"them" (top posters) and "us" (the sensible lot). Seeing your tagline here
in this forum I was again floored. I almost wrote something to you about
it yesterday.

Just so you know ... there's a better way, Victor. It's called "love".
Tear down the barriers and come out and help people in love. And if you
want to learn the fulness of love ... He is the man, named Jesus, who is
the Christ, the only Savior of mankind.

Best regards,
Rick C. Hodgin
 
V

Victor Bazarov

[..] The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.
[..]

Just curious, in what world a few hundred bytes is a waste of memory
worthy of consideration? Are you targetting an embedded system or a
legacy computer with 640K memory (last century technology)? Don't get
me wrong, please, it's just that I have often enough seen real
(significant) time wasted on finding a solution to save a few
microseconds or a few [hundred] bytes, that usually in the end cannot be
accounted for. I can understand when students do that in the course of
their studies, but I don't understand the need for it when creating a
product for others to consume.

I'm getting a lot of flack over this from many people on many lists. It's
like ... if I don't do it the way everybody else does then I'm the one who's
wrong. And because I look toward things which are important to me, and
because I choose to not waste memory where it doesn't need to be wasted,
while also simplifying the source code implementation of this task, that
it is somehow a bad choice.

No, not a bad choice, by any means IMO. Just an uncommon one.
Everybody has their priorities. Advice we *give* in part serves as
affirmation of our being right (or at least in the right area). If
something is recommended against our convictions, we have a choice -
either to change our convictions or ignore the advice. And we make
those choices constantly. Such is life.
FWIW, I had a working solution after getting the first access violation error
in the Visual Studio debugger and realizing why I got it. It took me a few
seconds to realize what was happening, even though it was unexpected. But,
the whole issue was one of those things I wanted to better understand. It
seemed (and still seems) a very silly imposition, that string literals
created in that way (as data pointed to in a read-write array) should always
be read-only unless they are explicitly cast through such a clunky syntax as
compound literals, a feature that not all C compilers even support.

I hope you don't have to learn the hard way why such a silly imposition
exists.
It was a mental exercise as much as anything else, a pursuit of a question,
to satiate curiosity. I wound up not using the solution, but just
discovering and testing it out. I learned many things in the process, not
the least of which was how to integrate GCC and Visual C++ together in
harmony. That alone was worth all the time I spent on it.

No argument here. Even if we don't gain anything, we always gain
experience.
Just curious, in what world would you deny giving help to someone in need
simply because they top-posted? I had someone in 2011 or 2012 on the
Trisquel mailing list tell me that I was a top poster and that he
wasn't going to help me. I didn't even know what he was talking about
and had to ask what that phrase "top poster" meant. When I found out
I was floored that such a ridiculous barrier exists between the
help-seekers, and the knowledge-holders on a forum like this.

It's my help to give, I can and may deny it on any basis I choose.
Would you help somebody who speaks rudely to you in the street or would
you simply turn away and keep minding your own business? In such a case
rudeness is in the eye of the beholder, of course. Similarly, I
perceive top-posting as rudeness and choose not to involve myself in a
message thread like that.

Incidentally, a way to have the last word in an argument with me *here*
is to top-post.
It really taught me something ... a concept that is so amazingly important
to only a select few, those who desire to divide people into groups of
"them" (top posters) and "us" (the sensible lot). Seeing your tagline here
in this forum I was again floored. I almost wrote something to you about
it yesterday.

Just so you know ... there's a better way, Victor. It's called "love".

Yes. So, if you care for *my* reply, now that you know that it is
important to *me*, and you can't get it if you top-post, you *might*
want to consider not top-post. Get it?

Practice what you preach.

And try not to preach.
Tear down the barriers and come out and help people in love. And if you
want to learn the fulness of love ... He is the man, named Jesus, who is
the Christ, the only Savior of mankind.

<sigh>

V
 
R

Rick C. Hodgin

Seems it affects string literals as well. This program works fine for me
with VS2012:

#include <iostream>
#pragma data_seg(".xxx")
char* list[] = {
"one",
"two",
"three"
};
int main()
{
list[0][0]='t';
list[0][1]='e';
list[0][2]='n';
std::cout << list[0] << "\n";
}

Paavo, this one of the suggestions I tried. In VS2008 it gives the
same access violation error.

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

Yes. So, if you care for *my* reply, now that you know that it is
important to *me*, and you can't get it if you top-post, you *might*
want to consider not top-post. Get it?

Did I top-post? I ask because I honestly don't know. I was under the
impression that top-posting meant you posted above the quoted content.
But maybe my understanding is still incorrect.

Best regards,
Rick C. Hodgin
 
V

Victor Bazarov

Did I top-post? I ask because I honestly don't know. I was under the
impression that top-posting meant you posted above the quoted content.
But maybe my understanding is still incorrect.

You did not top-post.

V
 
V

Victor Bazarov

Seems it affects string literals as well. This program works fine for me
with VS2012:

#include <iostream>
#pragma data_seg(".xxx")
char* list[] = {
"one",
"two",
"three"
};
int main()
{
list[0][0]='t';
list[0][1]='e';
list[0][2]='n';
std::cout << list[0] << "\n";
}

Paavo, this one of the suggestions I tried. In VS2008 it gives the
same access violation error.

VS2010 does the same. VS2012 differs - the resulting program runs OK.
I don't know whether it's a good idea for you to switch to VS2012 at
this point. This is obviously implementation-specific.

V
 
Ö

Öö Tiib

Changing the strings to fixed size will do the job:

#pragma data_seg()
char list[3][6] = {
{ "one" },
{ "two" },
{ "three"}
};

BTW the compiler will throw an error if you set the array dimensions too
small.

Hans-Peter, thank you for your response. I had considered using the [6]
add-on. The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.

So it is 8500 characters that you want to be mutable. You likely get
better memory usage AND better performance with array (or 'std::array')
of 'std::string's, but 8k of data are usually not worth of tinkering
unless you have hundreds of such.
 
R

Rick C. Hodgin

Changing the strings to fixed size will do the job:
#pragma data_seg()
char list[3][6] = {
{ "one" },
{ "two" },
{ "three"}
};
BTW the compiler will throw an error if you set the array dimensions too
small.

Hans-Peter, thank you for your response. I had considered using the [6]
add-on. The actual implementation is about 100 lines, which are source
code lines from another computer language. The lines vary in length from
a few characters up to over 80, the average probably being 15. I had
decided against using the [85] so as to not waste memory.

So it is 8500 characters that you want to be mutable. You likely get
better memory usage AND better performance with array (or 'std::array')
of 'std::string's, but 8k of data are usually not worth of tinkering
unless you have hundreds of such.

I have constraints on my design. I am currently writing a compiler that
takes some aspects of C and C++, but I will not support std::array or
std::string. As such, I am looking at some more fundamental approaches
to processing data as I intend eventually to compile my C code in my own
language.

My pursuit here to have the char* list[] array point to a list of read-write
values, instead of read-only values, also looks to that future of my compiler
design.

Best regards,
Rick C. Hodgin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top