I am having an issue where I have a C2440 error when compiling a C++ project in VS2005. The error is due some existing C code in another project which I depend on which casts a void pointer to either a char or int pointer.
The code resembles:
void * bbb;
... // some code which defines the void pointer
int * aaa = bbb;
However in C++ I need to specifically cast the type to be valid such as:
int * aaa = (int *)bbb;
My question is whether there exists a flag or compile option in VS2005 which allows my to compile my main project in C++ and ignore this error from depending projects I want to compile as C?
I would rather not change any of the original source as it is a shared project.
If you name the file "something.c", the compiler will [unless explicitly told otherwise] compile it as C (and thus happily accept your pointer conversion without using a cast). A file named "something.cpp" will be compiled as C++, and you will need a cast to convert a pointer to a different type, even if it's a void pointer.
The only way to do this was to edit the header files which caused the problem. It turned out to be a minor number of files which could be merged back into the shared projects.
There is no way to get around this in VisualC++. I had used -fpermissive to ignore the error in gcc.
So I just made the update to:
int * aaa = (int *)bbb;
Related
Using Netbeans 8.2 on Linux and GCC 8.1, unique_ptr::operator->() gives an erroneous warning
Unable to resolve template based identifier {var} and more importantly will not autocomplete member names.
Code compiles and runs just fine, and amazingly, the autocomplete still works with no warnings if a shared_ptr is used instead. I have no idea how that is possible. Here is a problematic example, for reference
#include <iostream>
#include <memory>
struct C { int a;};
int main () {
std::unique_ptr<C> foo (new C);
std::shared_ptr<C> bar (new C);
foo->a = 10; //Displays warning, does not auto-complete the members of C
bar->a = 20; //No warning, auto-completes members of C
return 0;
}
I've tried the following to resolve this issue with no luck:
Code Assistance > Reparse Project
Code Assistance > Clean C/C++ cache and restart IDE
Manually deleting cache in ~/.cache/netbeans/8.2
Looking through View > IDE Log for anything that may help
Setting both the C and C++ compilers to C11 and C++11 in project properties
Changing the pre-processing macro __cplusplus to both 201103L and 201402L
Creating a new Netbeans project and trying the above
A large variety of permutations of the above options in different orders
Again, everything compiles and runs just fine, it's just Code Assistance that is giving me an issue. I've run out of things that I've found in other stack overflow answers. My intuition tells me that shared_ptr working and unique_ptr not working is helpful, but I don't know enough about C++ to utilize that information. Please help me, I need to get back to work...
Edit 1
This stack overflow question, although referencing Clang and the libc++ implementation, suggests that it may be an implementation issue within GCC 8.1's libstdc++ unique_ptr.
TLDR Method 1
Add a using pointer = {structName}* directive in your structure fixes code assistance, and will compile and run as intended, like so:
struct C { using pointer = C*; int a;};
TLDR Method 2
The answer referenced in my edit does in fact work for libstdc++ as well. Simply changing the return type of unique_ptr::operator->() from pointer to element_type* will fix code assistance, compile and run as expected (the same thing can be done to unique_ptr::get()). However, changing things in implementations of the standard library worries me greatly.
More Information
As someone who is relatively new to c++ and barely understands the power of template specializations, reading through unique_ptr.h was scary, but here is what I think is messing up Netbeans:
Calling unique_ptr::operator->() calls unique_ptr::get()
unique_ptr::get() calls the private implementation's (__unique_ptr_impl) pointer function __unique_ptr_impl::_M_ptr(). All these calls return the __unique_ptr_impl::pointer type.
Within the private implementation, the type pointer is defined within an even more private implementation _Ptr. The struct _Ptr has two template definitions, one that returns a raw pointer to the initial template variable of unique_ptr, and the second that seems to strip any reference off this template variable, and then find it's type named pointer. I think that this is where Netbeans messes up.
So my understanding is when you call unique_ptr<elementType, deleterType>::operator->(), it goes to __unique_ptr_impl<elementType, deleterType>, where the internal pointer type is found by stripping elementType of any references and then getting the type named dereferenced(elementType)::pointer. So by including the directive using pointer =, Netbeans gets what it wants in finding the dereferenced(elementType)::pointer type.
Including the using directive is entirely superficial, evidenced by the fact that things will compile without it, and by the following example
#include <memory>
#include <iostream>
struct A{
using pointer = A*;
double memA;
A() : memA(1) {}
};
struct B {
using pointer = A*;
double memB;
B() : memB(2) {}
};
int main() {
unique_ptr<A> pa(new A);
unique_ptr<B> pb(new B);
std::cout << pa->memA << std::endl;
std::cout << pb->memB << std::endl;
};
outputs
1
2
As it should, even though in struct B contains using pointer = A*. Netbeans actually tries to autocomplete B-> to B->memA, further evidence that Netbeans is using the logic proposed above.
This solution is contrived as all hell but at least it works (in the wildly specific context that I've used it) without making changes to implementations of stl. Who knows, I'm still confused about the convoluted typing system within unique_ptr.
I'm trying to add the SQLite Amalgamation to my project. According to their page, I "Just copy the amalgamation into your source directory and compile it along with the other C code files in your project." I've also copied in sqlite3.h so I have access to the API.
However, any function call to the API, for instance:
sqlite3 *db;
int rc;
rc = sqlite3_open("test.db", &db);
results in the following error:
Invalid arguments '
Candidates are:
int sqlite3_open(const char *, * *) '
DataSettings.cpp
/FCS/src
line 24
Semantic Error
What am I doing wrong here? What have I neglected to set up?
The problem has the hallmarks of a name-mangling mismatch. Because C++ allows functions to be overloaded based on their argument types, C++ compilers must "mangle" function names they emit into object code to encode the argument types. C compilers do not do this, and do not expect it to be done to them. Specifying to a C++ compiler that a function has "C" linkage disables name mangling AND overloading of that function name; this is what extern "C" does.
Although C is similar in many ways to a subset of C++, the two are distinct languages. It is best to compile C code with a C compiler. One of your alternatives, therefore, is to build the C source of the sqlite amalgamation separately from your C++ code, into a library for instance, and link that with your C++ object files to produce the final executable.
I've inherited a C++ project that compiled fine in VS2005, but when I open it in VS2010 I get lots of IntelliSense erros like this:
IntelliSense: expression must have integral or enum type
Actually opening one of the cpp files in the project seems to cause the errors to appear.
Here's an example of the type of line that causes the error.
if (pInfoset->Fields->Item["Contact"]->Size <= 0)
I recognize the code, that's ADO syntax. You are battling a non-standard language extension that made COM programming easier in the previous decade. It allowed declaring properties on a C++ class, using the __declspec(property) declarator. An example:
class Example {
public:
int GetX(const char* indexer) { return 42;}
void PutX(const char* indexer, int value) {}
__declspec(property(get=GetX,put=PutX)) int x[];
};
int main()
{
Example e;
int value = e.x["foo"]; // Barf
return 0;
}
The IntelliSense parser was completely overhauled in VS2010 and re-implemented by using the Edison Design Group front-end. It just isn't compatible enough with the language extension and trips over the index operator usage. For which they can be forgiven, I'd say.
You can complain about this at connect.microsoft.com but I wouldn't expect miracles. The problem is still present in VS2012. A workaround is to stop using the virtual property and use the getter function instead, get_Item("Contact") in your case.
From something you said in the comments (about IntelliSense not finding a .tli file), the errors should go away once you build the solution. .tli (and .tlh) files are automatically-generated files that are created by the #import directive, but obviously you need to compile the files that have #import directives in order for those files to be generated (IntelliSense alone won't generate them).
I have a program which is to be used with a shared library.
I have one library (1) that is compiled with the methods full of code i.e.
class A
{
public:
int* funcA(int a, int b)
{
int* pInt = new int;
*pInt = a + (b * 20);
return pInt;
}
};
Then I have another library (2) with exactly the same name and interface with nothing in the methods i.e. a dummy class
class A
{
public:
int* funcA(int a, int b)
{
return 0;
}
};
(note: code just used to illustrate my problem)
If I compile against library 1 and then use library 1 at runtime, everything works as expected.
If I compile against library 2 and then use library 1 at runtime, the first called to funcA dies.
If I used nm -D libMy.so and look at the offset of funcA at runtime, it is different. Is this included in the binary?
Ive read various manuals and tutorials but am none the wiser as to how the compilation and runtime aspect causes this failure. I would have thought the interface is the same so the method would succeed.
Thanks.
The reason this is failing is that you have linked against a different library and thus (as you have seen) the function offsets are different. The linker has placed the offsets into your compiled binary and so it will only run against that library. In order to accomplish what you are attempting here you will need to use dynamic library loading see this SO question for more info.
EDIT:
With a little further reading, I came across this PDF, you may find it helpful.
(I don't have enough rep to just make a comment below your question)
This might be because the program is prelinked (Linux) or prebinded (MacOS) although I am not 100% sure. Some basic info about it on wikipedia below. Have you encountered this on your searches through the manuals?
http://en.wikipedia.org/wiki/Prelink
http://en.wikipedia.org/wiki/Prebinding
Did you forget a -fPIC option while compiling libraries? Please, add compilation commands.
I'm modifying an open source code(pngcrush) and want to include some c++ header (fstream,iostream)
Make complains there are no such files.
How do I include them?
Thank you
-EDIT-
adler32.c:60: error: ‘uLong adler32’ redeclared as different kind of symbol
zlib.h:1469: error: previous declaration of ‘uLong adler32(uLong, const Bytef*, uInt)’
adler32.c:60: error: ‘adler’ was not declared in this scope
adler32.c:60: error: ‘buf’ was not declared in this scope
adler32.c:60: error: ‘len’ was not declared in this scope
adler32.c:64: error: expected unqualified-id before ‘{’ token
adler32.c:12: warning: ‘uLong adler32_combine_(uLong, uLong, long int)’ declared ‘static’ but never defined
make: *** [adler32.o] Error 1
Compilation exited abnormally with code 2 at Wed Jan 5 18:51:02
at code
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long sum2;
unsigned n;
second edit -
I ended up compiling it as c code (using gcc) but with #ifdef __cplusplus extern "C"{} #endif .. I put that #ifdef following other c codes of the projects.
It compiles now, but with an warning (ranlib has no symbols, i googled it, looks like it only happens in mac os)
ar rcs libpngcrush.a png.o pngerror.o pngget.o pngmem.o pngpread.o pngread.o pngrio.o pngrtran.o pngrutil.o pngset.o pngtrans.o pngwio.o pngwrite.o pngwtran.o pngwutil.o adler32.o compress.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o simplepngcrush.o
/usr/bin/ranlib: file: libpngcrush.a(pngpread.o) has no symbols
also, when I link this libpngcrush.a to my c++ code,
it dies when I call the function that's in the library for the first time.
Run till exit from #0 0x0000000100089071 in simplepngcrush () at tokenlist.h:118
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00000001000890f8 in simplepngcrush () at tokenlist.h:118
Looks like, I can't even get to the first line of the called function.
You cannot. C++ source code cannot be use from C.
The only way is to switch to C++: transform your C code in C++ (this often requires no or little modification to the code, only to the build scripts in order to switch compiler) and then use C++ header and tools.
EDIT:
C++ uses a different way than C to identify symbols (functions, variable and stuff).
uLong ZEXPORT adler32(adler, buf, len) is just called adler32 by C, while it could be called _Z7adler32lPKci in C++. This is to provide stuff like overloading.
If you want to let the compiler give it the same name that C gives, you can put the declaration in an extern "C":
extern "C"
{
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
}
I would advise against it. If the project is written in C, keep it in C and use FILE* and printf etc.
There is a difference however if you are integrating C++ with C and want to either:
- write a module in C++ but give it a C interface
- write a module in C++ and call a C interface.
Although you could expose fstream to C by giving iostream a C interface I do not really see a great advantage in doing it. You cannot overload streaming out functions, for example (i.e. using the same name with different types being printed).
For your own code though in your own library, you may well wish to write in C++ and give it a C interface. In such a case you use forward-declarations of your classes (calling them struct) and free-functions that access it using pointers, of course, as C does not have references.
Users always deal with pointers to your class and of course they need a function to dispose of them (they don't just call free).
your C code will be compiled with a C compiler that will not recognise things like class, template, new, delete etc so there is no way to use the C++ library from C
You are likely to also encounter errors if you try compile your C code as C++ due to a stricter type system. Also your colleagues may not appreciate you transforming a C module to C++.
try to achieve your goal using C file io and C streams; FILE, fopen, fread, fwrite, fprintf, stdout, stderr etc
You don't. If the code is C, you cannot just throw C++ headers in and expect it to work. C and C++ are two different languages altogether.
Instead, move to building the entire thing in C++, which may well involve not-insignificant changes to the codebase, depending upon how it's written.
(This isn't a recommendation; it's just the only way you'll be able to use those headers. Instead, if it's written in C, stick to C. Then it'll remain maintainable with the original codebase.)