Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Link object files from VC++ and GCC?

88 views
Skip to first unread message

Rick C. Hodgin

unread,
Jan 23, 2014, 12:39:18 PM1/23/14
to
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

Rick C. Hodgin

unread,
Jan 23, 2014, 12:40:27 PM1/23/14
to
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?

Alf P. Steinbach

unread,
Jan 23, 2014, 1:14:11 PM1/23/14
to
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

Victor Bazarov

unread,
Jan 23, 2014, 2:20:49 PM1/23/14
to
On 1/23/2014 12:40 PM, Rick C. Hodgin wrote:
> 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
--
I do not respond to top-posted replies, please don't ask

Robert Wessel

unread,
Jan 23, 2014, 2:33:13 PM1/23/14
to
On Thu, 23 Jan 2014 09:40:27 -0800 (PST), "Rick C. Hodgin"
<rick.c...@gmail.com> wrote:

>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?


ICC will probably do it, it implements most GCC extensions.

Scott Lurndal

unread,
Jan 23, 2014, 2:43:43 PM1/23/14
to
gcc hasn't used COFF format for over a decade or more. ELF has been
the standard on unix and unix-like operating systems since 1990.

You are correct, however, in that it doesn't make any sense to do this.

Scott Lurndal

unread,
Jan 23, 2014, 2:52:44 PM1/23/14
to
My Bad - missed the windows references. Not surprising that they're
25 years out of date :-)

Rick C. Hodgin

unread,
Jan 23, 2014, 2:58:26 PM1/23/14
to
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]; 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.

Rick C. Hodgin

unread,
Jan 23, 2014, 3:06:12 PM1/23/14
to
Should be:

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

Rick C. Hodgin

unread,
Jan 23, 2014, 3:33:59 PM1/23/14
to
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]; i++)
{
list[i][0] = '!'; // Prove it's read-write
puts(list[i]); // Show it
}
}
===========END===========

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

Rick C. Hodgin

unread,
Jan 23, 2014, 3:45:22 PM1/23/14
to
On Thursday, January 23, 2014 2:20:49 PM UTC-5, Victor Bazarov wrote:
> 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.

David Brown

unread,
Jan 23, 2014, 5:13:01 PM1/23/14
to
On 23/01/14 18:40, Rick C. Hodgin wrote:
> 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.


Hans-Peter

unread,
Jan 24, 2014, 3:34:26 AM1/24/14
to

"Rick C. Hodgin" wrote in message
news:0f20b7fc-b6b1-46d6...@googlegroups.com...
>
> 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

Rick C. Hodgin

unread,
Jan 24, 2014, 8:49:53 AM1/24/14
to
On Friday, January 24, 2014 3:34:26 AM UTC-5, Hans-Peter wrote:
> "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.

Victor Bazarov

unread,
Jan 24, 2014, 9:31:40 AM1/24/14
to
On 1/24/2014 8:49 AM, Rick C. Hodgin wrote:
> [..] 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.

Rick C. Hodgin

unread,
Jan 24, 2014, 10:53:11 AM1/24/14
to
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.

Victor Bazarov

unread,
Jan 24, 2014, 11:44:40 AM1/24/14
to
On 1/24/2014 10:53 AM, Rick C. Hodgin wrote:
> On Friday, January 24, 2014 9:31:40 AM UTC-5, Victor Bazarov wrote:
>> On 1/24/2014 8:49 AM, Rick C. Hodgin wrote:
>>> [..] 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.

>> 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'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
--

Paavo Helde

unread,
Jan 24, 2014, 12:40:33 PM1/24/14
to
"Hans-Peter" <Hans-Pet...@sap.com> wrote in
news:lbt8ip$dos$1...@news.sap-ag.de:

>
> "Rick C. Hodgin" wrote in message
> news:0f20b7fc-b6b1-46d6...@googlegroups.com...
>>
>> 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:

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";
}

Cheers
Paavo



Rick C. Hodgin

unread,
Jan 24, 2014, 1:12:02 PM1/24/14
to
On Friday, January 24, 2014 12:40:33 PM UTC-5, Paavo Helde wrote:
> 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.

Rick C. Hodgin

unread,
Jan 24, 2014, 1:14:21 PM1/24/14
to
On Friday, January 24, 2014 11:44:40 AM UTC-5, Victor Bazarov wrote:
> 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.

Victor Bazarov

unread,
Jan 24, 2014, 1:33:51 PM1/24/14
to
You did not top-post.

Victor Bazarov

unread,
Jan 24, 2014, 1:39:39 PM1/24/14
to
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.

Öö Tiib

unread,
Jan 25, 2014, 12:01:43 PM1/25/14
to
On Friday, 24 January 2014 15:49:53 UTC+2, Rick C. Hodgin wrote:
> On Friday, January 24, 2014 3:34:26 AM UTC-5, Hans-Peter wrote:
>
> > 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.

Rick C. Hodgin

unread,
Jan 25, 2014, 5:30:32 PM1/25/14
to
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.
0 new messages