I'm converting the header files of a C library to D modules, and was wondering how I should handle C strings.
Using DMD 1, this works:
void f(char* s); // Definition for C library's function.
But using DMD 2 (which I personally use, but I would like the modules to work for both) strings are const, so to get the same code using the modules to work requires
void f(const(char)* s); // Definition for C library's function.
What should I do? Just use char* and make the 'client' code make the strings mutable somehow? Or modify the type depending on the version of the compiler compiling the code? If the former, what's the best way to make them mutable? I thought .dup would do it, but the compiler wasn't having a bar of it. If the latter, how would I go about doing it? I tried this:
version (D_Version2) {
alias const(char)* charptr;
} else {
alias char* charptr;
}
void f(charptr s);
But alas, the DMD 2 version isn't valid code for DMD 1, and all code in version blocks must be valid code for the compiler compiling the code, even if the code wouldn't be included in the resulting executable. So currently the code compiles in both, but you have to modify the alias first which, as you can imagine, isn't ideal.
You can use the mixin construct to use language-version-specific code that isn't valid in all versions. Example:
static if(version_major<2)
{
alias char* charptr;
}
else
{
mixin("alias const(char)* charptr;");
}
Regarding your actual question, I would suggest doing the same as when interfacing C libraries with C++ - define a type that's const(char)* for D2 and char* for D1, but only use it when appropriate (for example, if a function takes a char* for a buffer to write to, it probably wouldn't be appropriate to name const(char)* something as generic as "charptr"). LPCSTR could work ;)
I didn't understand the "What's the best way to make them mutable" question.
Don't use mixins for this, it's the wrong tool for the job. What you really need is the 'version' statement, you can read about it in the Conditional Compilation page here: http://www.digitalmars.com/d/2.0/version.html
It won't compile / look at code that is for a different version. This allows to build different code for different D versions, or different OS's, different whatever.
Mixins probably works, but it's a heavy tool, doesn't have highlighted code (inside the quotes) and is just overly complicating things. The version statement is perfectly suited for this problem.
Related
I have a few logging functions that I commonly use for different Arduino programs. Since I use them so much, I decided to try to make a custom library for them. Unfortunately, the compiler crashes at the header file with the error:
unknown type name 'String'
I'm a bit confused as to why this is happening because I am including the standard Arduino libraries (which I believe should contain the String class) at the top of my header. Here's the whole thing:
#ifndef logging_h
#define logging_h
#include "Arduino.h"
void logEvent(String msg);
void debugOut(String msg);
void errOut(String err);
void document(String parameter, float value);
#endif
I reinstalled the Arduino IDE (1.0.5) so I think I should have the most recent standard library. If anyone has some suggestions I would really appreciate it.
(This answer is based on our discussion in comments.)
The problem was that the source file for your library was named *.c. That caused the compiler to treat it as C code instead of C++, which means it couldn't handle classes/objects (such as String).
Naming the file *.cpp instead lets the compiler treat it correctly as C++ code.
I had same issue yesterday. The code you included in your question should be your .h file, isn't? My question is: is your library written in C or in C++?
I assume you use C code.
You can't import code from in a user C library with the Arduino IDE. The reason is that use C++ code, and it can't be called from your C library.
Solution: rewrite your library in C+, it's not too difficult.
You can find a lot of help on google on how to write library in C++. You can also check my example at https://github.com/romain-viollette/AverageFilter/
best regards,
i am trying to Print some data in wxstring using printf function but its crashing in run time in LINUX but not in windows
here is my code:
wxString str1,str2;
str1 = "Elements";
str2.Printf( _U("%s"),str1);
This is working in windows but not in linux , if i change it below its working in linux also
str2.Printf( _U("%s"),str1.c_str());
why its not taking str1 as argument.
Note:This sentence i am using throughout the workspace is there any common way to do this in linux instead of changing in all places
The only "fix" is to upgrade to wxWidgets 3.0 where wxString::Printf() and other similar functions are (pseudo) variadic templates and so do work correctly with objects and not only raw pointers. In wxWidgets 2.8 they are variadic functions and, according to the language rules, can't work with the objects and no, there is no way around this.
This help clarify you:
The following code:
wxString str;
str.Printf(wxT("My string is %s"), wxString("whatever"));
does not work. Unfortunately, it may seem to work fine under Windows because of a compiler quirk there but passing a wxString object to a function taking a variable number of arguments such as Printf() is undefined behaviour in C++. Accordingly, it will simply crash under most platforms but may even "work" on some of them.
You must use c_str() to make the above code work, i.e. write this instead:
wxString str;
str.Printf(wxT("My string is %s"), wxString("whatever").c_str());
Note that g++ should give you an error when passing an object to a vararg function like this -- another reason to compile your code with g++ even if you normally use another compiler.
I get error during build in Ubuntu.
And the error is as following:
ISO C++ forbids declaration of `wstring' with no type
In order to solve this problem,I have to define the wstring by myself.
So who knows how to define wstring?
In order to use wstring you have to add #include<string> and, preferrably, use its fully qualified name std::wstring.
UPDATE:
In the case that your compiler, for some reason, does not support std::wstring, you can try with the following typedef (taken directly from bits/string_fwd.h and tweaked to add the missing std::).
typedef std::basic_string<wchar_t> wstring;
Note that this depends on wchar_t being defined, and according to this:
In C++, wchar_t is a distinct fundamental type (and thus it is not defined in nor any other header).
If your compiler doesn't have support for wchar_t there's no (easy) way to define it as far as I know.
This is part of a series of at least two closely related, but distinct questions. I hope I'm doing the right thing by asking them separately.
I'm trying to get my Visual C++ 2008 app to work without the C Runtime Library. It's a Win32 GUI app without MFC or other fancy stuff, just plain Windows API.
So I set Project Properties -> Configuration -> C/C++ -> Advanced -> Omit Default Library Names to Yes (compiler flag /Zl) and rebuilt. Let's pretend I have written a suitable entry point function, which is the subject of my other question.
I get two linker errors; they are probably related. The linker complains about unresolved external symbols __fltused and _memcpy in foobar.obj. Needless to say, I use neither explicitly in my program, but I do use memcpy somewhere in foobar.cpp. (I would have used CopyMemory but that turns out to be #defined to be identical to memcpy...)
(I thought I could get rid of the memcpy problem by using a compiler intrinsic, like #pragma intrinsic(memcpy), but this makes no difference.)
If I look at the preprocessor output (adding /P to the compiler command line), I see no references to either __fltused or _memcpy in foobar.i.
So, my question is: Where do these linker errors come from, and how do I resolve them?
__fltused implies you are using or have at least declared some floats or doubles. The compiler injects this 'useless' symbol to cause a floating support .obj to get loaded from the crt. You can get around this by simply declaring a symbol with the name
#ifdef __cplusplus
extern "C" {
#endif
int _fltused=0; // it should be a single underscore since the double one is the mangled name
#ifdef __cplusplus
}
#endif
WRT _memcpy - memcpy is a __cdecl function, and all cdecl functions get an automatic _ as part of their decoration. so, when you say "__cdecl memcpy" - the compiler & linker go looking for a symbol called '_memcpy'. Intrinsic functions - even explicitly requested - can still be imported if the build settings have debug settings that contra-indicate intrinsics. So you are going to need to implement your own memcpy and related functions at some point anyway.
I recommend setting the "generate assembly listing" (or some such) compiler option for foobar.cpp once, and then inspecting the assembler code. This should really tell you where these symbols are used.
I'm working on a cross platform project that uses STL. The other compiler includes STL support by default, but in VS2005 I need to add the following before the class definitions that use STL items:
#include <cstdlib>
using namespace std;
Is there a VS2005 option that would set this automatically? It's just a bit tedious to work around. I'm just trying to avoid lots of #ifdefs in the source -
EDIT: The other compiler is the IAR workbench for the ARM 926x family. Perhaps I should get them to explicitly do the includes?
Also - is "std::map<>" preferred over "using namespace std; map<>" ?
All compilers should require you to include those lines. If they don't, then they're just encouraging you to write non-portable code because you're relying on certain headers to be included automatically and you're relying on certain names to be in scope implicitly.
I don't mean to say that those two lines should always be required, though. I only mean that if the rest of your code is written to use things declared in the cstdlib header and in the std namespace, then those two lines need to appear first, and the compiler shouldn't act as though they are there when they really aren't.
Check whether your other compiler has some settings to disable this implicit code. If it doesn't, then it's probably a very, very old compiler, and you should consider not using it and not supporting it anymore.
Try refering to STL components by their namespace-qualified name (i.e. std::vector).
Doing a global 'using namespace std' is usually a bad idea.
Or maybe I'm not understanding the question.
The IAR compiler does not support the std namespace (I'm not sure why, because it does support namespaces in general if I remember right).
If you look in the runtime headers for IAR you'll see that they do some macro gymnastics to work around that (the runtime is licensed from Dinkumware, who provide runtimes for quite a few compilers).
You may need to do something similar if you want your stuff to work in multiple environments. A possible cleaner alternative is to just include the "using namespace std;" directive. I might be wrong, but I think the IAR compiler essentially ignored it (it didn't mind that you were using a namespace it didn't know about). A lot of people will think that's ugly, but sometimes you gotta do what the compiler you have wants you to do.
In general you should avoid "using namespace X", especially in header files (because everyone who includes your header gets that namespace too whether they want it or not), and especially for namespace std (because it's so big and the potential for name collisions is big).
Instead, in header files refer to names by their fully qualified form, e.g.:
// for plain functions
void foo(std::map<int> intMap);
// for classes
class person {
std::string name_;
public:
person(std::string name);
// ...
};
Then, in code files, you can do "using", but prefer using specific items in the namespace rather than pulling in the entire namespace. e.g.:
using std::map;
using std::string;
void foo(map<int> intMap) { ... };
person::person(string name) : name_(name) { ... };
etc. This way you avoid impacting others including your headers, and you avoid pulling in potentially zillions of names that might cause a collision with other stuff.