Compiling C DLLs for reuse in MC++?

W

WebSnozz

I have an application written in C that does a lot of low level stuff.
It does a lot of things like casting from void*'s. I want to create a
new GUI for it in either C# or MC++, but reuse the existing code.

The options I've considered so far:

1. Create a new MC++ GUI project and add the *.c files to them and mark
them with pragma unamanged. However, the /clr option does not compile
*.c files, so I rename them to *.cpp, and now they will not compile due
to c operations not legal in cpp. Most of the compilation errors are
related to perform casts such as:
(classname*)somethingDeclaredAsVoidPointer;//compile error indicates
unable to perform cast from void* to classname*.

I think there is a specific syntax I can use to make these casts
compile successfully(I understand these types of casts are not type
safe), but my goal is to modify the code as little as possible, and
there a very large number of errors in the C code when I try compiling
as cpp. It's not a big task to change them, but I wanted to try and
use the same c files for compiling the old version of the app also,
which would probably involve some #ifdef statements to allow
inclusions/exclusion of code depending on what project it's being
compiled from.

2. Compile the C code as a DLL. Make calls to the DLL from MC++ or C#
whenever a function is needed. I am not quite sure how to do this. I
took the C project, and changed the output type from Application to DLL
and with a few tweaks, got it to compile successfully. However, if I
set the DLL project as a dependency of my C++ project, then it gives me
errors stating the I cannot link with a native DLL because the clr
option is enabled(referring to the clr option in the MC++ project).

So I have no idea how to use the native DLL from MC++. The only
example I found was actually compiling the C code as *.cpp files with
the /clr:blush:ldsyntax option. This option is not compatible with *.c
files, and changing them to *.cpp files puts me back where I was with
option #1.

This is the part where I lack understanding of native C/C++ DLL's.
I've never made a native DLL before and successfully used it. I have
no problems in .NET, but of course things seem to be alot simpler in
..NET, as public class are automatically exposed, and register the DLL,
and then other applications just referrence the DLL via it's namespace.

How does my MC++ application get knowledge of and make function calls
into functions in the native C DLL?

3. Have the C program continue to run as it's own application, but not
show it's GUI, and instead, post message or communicate with the C# or
MC++ application. I don't know if I can do this with some kind of
posting of messages, or communicating over sockets. I have some
conceptual ideas, but the ideas are way beyond me.

4. Compile the MC++ as a native DLL, and have the C application make
calls into the DLL to spawn the GUI and communicate over function calls
which make requests of the GUI thread. I am pretty confident with
threading in either context. The part that I am wary of, is again how
to make DLL calls. I haven't tried this, but I imagine I will have the
same problem as #2. I don't have a lot of experience with native DLLs,
and if I try to implement this just as it would have been in old school
C/C++, then I'm afraid my efforts will not be fuitful when I found out
that for some reason, once again the /clr option tells me I can't link
to a MC++ DLL from a C application. If there's something special I
need to do, I need to know that.

I think option #2 or #4 are probably my most preferred options, but I
am having trouble figuring out how to give one application "knowledge"
of the other DLL. I'm used to scenarios in C# where I just add a
reference, and walla, I can use the namespace, or in C++ where I just
set a dependency to the DLL and VS seems to magically take care of
linking them together. I am spoiled by VC++. The only time I haven't
used it either when using languages not supported by VS, or when
writing under linux, but have never made a DLL in either of those
contexts.


Any suggestions are appreciated, or pointing me to good examples of
these scenarios that are using truly native C(not cpp files compile
with /clr:blush:ldsyntax).
 
B

Bruno van Dooren [MVP VC++]

I have an application written in C that does a lot of low level stuff.
It does a lot of things like casting from void*'s. I want to create a
new GUI for it in either C# or MC++, but reuse the existing code.

The options I've considered so far:
2. Compile the C code as a DLL. Make calls to the DLL from MC++ or C#
whenever a function is needed. I am not quite sure how to do this. I
took the C project, and changed the output type from Application to DLL
and with a few tweaks, got it to compile successfully. However, if I
set the DLL project as a dependency of my C++ project, then it gives me
errors stating the I cannot link with a native DLL because the clr
option is enabled(referring to the clr option in the MC++ project).

This is what I would do if your code is pure C code. It has the advantage
that you don't have to change anything to existing code.
Could you paste the exact error message?
This is the part where I lack understanding of native C/C++ DLL's.
I've never made a native DLL before and successfully used it. I have
no problems in .NET, but of course things seem to be alot simpler in
.NET, as public class are automatically exposed, and register the DLL,
and then other applications just referrence the DLL via it's namespace.

How does my MC++ application get knowledge of and make function calls
into functions in the native C DLL?

Just include the include file, and link with the lib file.
3. Have the C program continue to run as it's own application, but not
show it's GUI, and instead, post message or communicate with the C# or
MC++ application. I don't know if I can do this with some kind of
posting of messages, or communicating over sockets. I have some
conceptual ideas, but the ideas are way beyond me.

lots of overhead. you don't want to do this.
4. Compile the MC++ as a native DLL, and have the C application make
calls into the DLL to spawn the GUI and communicate over function calls
which make requests of the GUI thread. I am pretty confident with
threading in either context. The part that I am wary of, is again how
to make DLL calls. I haven't tried this, but I imagine I will have the
same problem as #2. I don't have a lot of experience with native DLLs,
and if I try to implement this just as it would have been in old school
C/C++, then I'm afraid my efforts will not be fuitful when I found out
that for some reason, once again the /clr option tells me I can't link
to a MC++ DLL from a C application. If there's something special I
need to do, I need to know that.

I would not do this either. you would have to change you existing code, and
it would take more designing and testing.

www.codeproject.com is always a good place to start.

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
B

Ben Voigt

WebSnozz said:
I have an application written in C that does a lot of low level stuff.
It does a lot of things like casting from void*'s. I want to create a
new GUI for it in either C# or MC++, but reuse the existing code.

Since you mention /clr:blush:ldSyntax, you must have VC++ 2005, which is C++/CLI,
not Managed C++. I hate to be picky about this, but the two are utterly
incompatible. Even with /clr:blush:ldSyntax, VC++ 2005 doesn't follow the rules
for MC++.
The options I've considered so far:

1. Create a new MC++ GUI project and add the *.c files to them and mark
them with pragma unamanged. However, the /clr option does not compile
*.c files, so I rename them to *.cpp, and now they will not compile due
to c operations not legal in cpp. Most of the compilation errors are
related to perform casts such as:
(classname*)somethingDeclaredAsVoidPointer;//compile error indicates
unable to perform cast from void* to classname*.

There are very few things in C that the C++ compiler rejects... the only
thing I ever have to do is add any missing prototypes.

Your statement is a little suspicious
"(classname*)somethingDeclaredAsVoidPointer" because C doesn't have classes.
I'm going to take a wild guess and say that the cast target type is a
function pointer... you can't cast between data and function pointers in
C++. Any other C-style cast would still be valid.

You can make this C++ compatible, while staying valid C, as follows:

typedef void (*functionptr_t)();

and use functionptr_t instead of void* when you need to cast function
pointers.
I think there is a specific syntax I can use to make these casts
compile successfully(I understand these types of casts are not type
safe), but my goal is to modify the code as little as possible, and
there a very large number of errors in the C code when I try compiling
as cpp. It's not a big task to change them, but I wanted to try and
use the same c files for compiling the old version of the app also,
which would probably involve some #ifdef statements to allow
inclusions/exclusion of code depending on what project it's being
compiled from.

You can do this as well. I have a third-party C library which I compile
without /clr into a static library. I then have a managed C++/CLI assembly
that links the native library (.lib) in with no problem. Note: you have to
use /clr, not /clr:pure or /clr:safe, to interact with native code and data.

The only #if you would need is the well-known incantation for header files
shared between C and C++:
#if __cplusplus
extern "C"{
#endif

....

#if __cplusplus
}
#endif

Don't use #ifdef, because I know of at least one major compiler than defines
__cplusplus to 0 in .c files when compiling a mixture of C and C++.

If the C code was originally a standalone application, you may end up with a
collision on "main". The right thing to do here is make a static library
with all the reuseable pieces, not including main.
 
W

WebSnozz

Thank you for your response.

"Just include the include file, and link with the lib file"

Just to clarify some things:
So in the MC++ program I would just add the c lib file as an item in
the project, or specify in the project Linker properties the location
of the lib as additional libraries to link?

Should VS be generating a lib file automatically just by me making the
output type DLL? If the answer is no, then I will try to research this
myself. If the answer is yes, then I am confused because there is only
a DLL file, no lib. (Maybe because I haven't started defining
functions as extern or added the DLLMain or whatever the main is for a
DLL.)

The header file you refer to will be the one where I declare function
signatures as extern? I am not knowledgeable of those things yet, but
I'm sure I can find lots of documentation on making native C DLLs. I
just want to verify that you are referring to the .h files made
especially for the native C DLL, and not referring to the *.h files
that were a part of the original C executable application for it's own
use?

Thanks again.
 
W

WebSnozz

Thanks Ben,

I remember I was able to compile the c program as a static library, but
I had trouble linking. Is going into the VC++ GUI project and setting
a dependancy on the C lbirary project the correct way to link them? Or
should I be going under the Linker section of the project properties
and pointing it to where the library is at? I have also seen people
just add the *.lib files into the project under solution explorer, but
I am not sure if this automatically causes them to be linked?

I will try your suggestions when I get home, but if you could clarify
the above for me, thanks.


Yes indeed, it is VS 2005. The only reason I mentioned /clr:blush:ldsyntax
was because the one example I saw used that for the C(but *.cpp files)
DLL:
http://www.etro.vub.ac.be/Personal/bjansen/dlls/interfacing.html#cdll

But this example didn't really work well for me because my project
chokes on the /clr:blush:ldsyntax option that they use, and without it I
wasn't able link to the DLL. Anyhow, I am curious about what you mean
in regards to VS2005 being "VC++ 2005, which is C++/CLI, not Managed
C++". I will read up on this. Are you implying that I might find 2003
easier for this sort of thing?


You are right about the error not being class related. Those cases
were actually casting to a struct or sometimes a typedef of some sort
of primitive type like a char*. Whenever I see something that is not a
standard type name, I immediately think of class when I really should
think, "Type name defined by user which could be a typedef, class,
struct, or who knows what else."

There are also a lot of function pointers also. I haven't gone through
and read every error message to see if any are function pointer
related. I will look at the exact error messages again when I get
home, and perhaps I will be more persistent now that you've given me
encouragement on these things.
 
B

Ben Voigt

WebSnozz said:
Thanks Ben,

I remember I was able to compile the c program as a static library, but
I had trouble linking. Is going into the VC++ GUI project and setting
a dependancy on the C lbirary project the correct way to link them? Or
should I be going under the Linker section of the project properties
and pointing it to where the library is at? I have also seen people
just add the *.lib files into the project under solution explorer, but
I am not sure if this automatically causes them to be linked?

I actually have two native static libs in my current workspace. One, I
don't even have source for, just dropped the .lib into solution explorer and
imported the vendor header file like this:

extern "C" {

#include "nameofthelibrary.h"

};

The other one I compiled from source, and in the C++/CLI project, I
right-click the project in Solution Explorer, choose References, and added a
project reference which automatically sets the build order dependency and
pulls the .lib into the linker. The C++/CLI mantra is "It Just Works", and
well, it does. For that one I had to match the vendor's structure packing
because the buffers are passed intact to a driver binary:

#pragma pack(push, 1)

extern "C" {

#include "nameoftheotherlibrary.h"

}

#pragma pack(pop)

I will try your suggestions when I get home, but if you could clarify
the above for me, thanks.


Yes indeed, it is VS 2005. The only reason I mentioned /clr:blush:ldsyntax
was because the one example I saw used that for the C(but *.cpp files)
DLL:
http://www.etro.vub.ac.be/Personal/bjansen/dlls/interfacing.html#cdll

But this example didn't really work well for me because my project
chokes on the /clr:blush:ldsyntax option that they use, and without it I
wasn't able link to the DLL. Anyhow, I am curious about what you mean
in regards to VS2005 being "VC++ 2005, which is C++/CLI, not Managed
C++". I will read up on this. Are you implying that I might find 2003
easier for this sort of thing?

No! VC++ 2002/2003's Managed C++ is evil incarnate.
 
A

AaronLShumaker

Thanks again Ben.

Ben said:
I actually have two native static libs in my current workspace. One, I
don't even have source for, just dropped the .lib into solution explorer and
imported the vendor header file like this:

extern "C" {

#include "nameofthelibrary.h"

};

The other one I compiled from source, and in the C++/CLI project, I
right-click the project in Solution Explorer, choose References, and added a
project reference which automatically sets the build order dependency and
pulls the .lib into the linker. The C++/CLI mantra is "It Just Works", and
well, it does. For that one I had to match the vendor's structure packing
because the buffers are passed intact to a driver binary:

#pragma pack(push, 1)

extern "C" {

#include "nameoftheotherlibrary.h"

}

#pragma pack(pop)



No! VC++ 2002/2003's Managed C++ is evil incarnate.
 
G

Guest

"Just include the include file, and link with the lib file"
Just to clarify some things:
So in the MC++ program I would just add the c lib file as an item in
the project, or specify in the project Linker properties the location
of the lib as additional libraries to link?

If you do it manually, you have to specify it in the linker input tab.
You can also make it a dependency, in which case it happens automatically.
Should VS be generating a lib file automatically just by me making the
output type DLL? If the answer is no, then I will try to research this
myself. If the answer is yes, then I am confused because there is only
a DLL file, no lib. (Maybe because I haven't started defining
functions as extern or added the DLLMain or whatever the main is for a
DLL.)

Yes, it should do this, but it only does this if there are exported
functions. if there are no exports, it will not create a lib file.
The header file you refer to will be the one where I declare function
signatures as extern?

yes, those header files.
but extern is not enough.
you have to use either __declspec(dllexport) or add a DEF file to your
project.
I am not knowledgeable of those things yet, but
I'm sure I can find lots of documentation on making native C DLLs. I
just want to verify that you are referring to the .h files made
especially for the native C DLL, and not referring to the *.h files
that were a part of the original C executable application for it's own
use?

No, I mean the header file that has the declaration for the exported
functions.
 
B

Ben Voigt

Bruno van Dooren said:
If you do it manually, you have to specify it in the linker input tab.
You can also make it a dependency, in which case it happens automatically.


Yes, it should do this, but it only does this if there are exported
functions. if there are no exports, it will not create a lib file.


yes, those header files.
but extern is not enough.
you have to use either __declspec(dllexport) or add a DEF file to your
project.

for a .lib, you just need extern. For a .dll you need also
declspec(dllexport) when building the dll, and declspec(dllimport) in
clients.
 

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

Top