I am developing a TCP/IP client that has to deal with a proprietary binary protocol. I was considering using user-defined types to represent the protocol headers, and using CopyMemory to shuffle data to and from the UDT and a byte array. However, it appears that VB6 adds padding bytes to align user-defined types. Is there any way to force VB6 to not pad UDT's, similar to the #pragma pack directive available in many C/C++ compilers? Perhaps a special switch passed to the compiler?
No.
Your best bet is to write the low level code in C or C++ (where you do have #pragma pack), then expose the interface via COM.
There is not any way to force VB6 to not pad UDT's, similar to the #pragma pack directive available in many C/C++ compilers, but you can do it the other way around.
According to Q194609 Visual Basic uses 4 bytes alignment and
Visual C++ uses 8 bytes by default.
When using VB6 to call out to a C DLL, I used the MS "pshpack4.h" header files to handle the alignment because various compilers do this in different ways, as shown in this (rather edited) example:
// this is in a header file called vbstruct.h
...
# define VBSTRING char
# define VBFIXEDSTRING char
# define VBDATE double
# define VBSINGLE float
# ifdef _WIN32
# define VBLONG long
# define VBINT short
# else // and this was for 16bit code not 64bit!!!!
# define VBLONG long
# define VBINT int
# endif
...
# include "pshpack4.h"
...
typedef struct VbComputerNameStruct
{
VBLONG sName;
VBSTRING ComputerName[VB_COMPUTERNAME_LENGTH];
} VbComputerNameType;
typedef struct VbNetwareLoginInfoStruct
{
VBLONG ObjectId;
VBINT ObjectType;
VBSTRING ObjectName[48];
} VbNetwareLoginInfoType;
...
# include "poppack.h"
Related
So I'm trying to compile this project : https://github.com/dmitrystu/libusb_stm32 with Segger Embedded studio which uses gcc. The process is choking on this error :
pasting formed 'u"Open source USB stack for STM32"', an invalid preprocessing token
which is caused by this line :
static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
So USB_STRING_DESC is a macro :
#define USB_STRING_DESC(s) {.bLength = sizeof(CAT(u,s)),.bDescriptorType = USB_DTYPE_STRING,.wString = {CAT(u,s)}}
And CAT is a macro CAT(x,y) x##y. The intent must be to convert a string of type 8-bit char into a 16-bit Unicode type but the compiler doesn't like it. Is there some #include or compiler setting that may be missing that I have to add here? Clearly the author of this code expects it to work so there must be some fault in my setup.
Also I'm not clear on how the sizeof() operation is supposed to work here. As I understand it there is no way to get the length of a string at compile time so that operation will always return the size of a pointer.
In response to Keith's question, the gcc version is 4.2.1. Poking around the compiler settings the default option is the C99 standard, when I changed it to C11 everything compiled just fine. Thanks!
I'm aware of many similar questions on this site. I really like the solution mention in the following link:
https://stackoverflow.com/a/25021520/884553
with some modification, you can include text file at compile time, for example:
constexpr const char* s =
#include "file.txt"
BUT to make this work you have to add string literal prefix and suffix to your original file, for example
R"(
This is the original content,
and I don't want this file to be modified. but i
don't know how to do it.
)";
My question is: is there a way to make this work but not modifying file.txt?
(I know I can use command line tools to make a copy, prepend and append to the copy, remove the copy after compile. I'm looking for a more elegant solution than this. hopefully no need of other tools)
Here's what I've tried (but not working):
#include <iostream>
int main() {
constexpr const char* s =
#include "bra.txt" // R"(
#include "file.txt" //original file without R"( and )";
#include "ket.txt" // )";
std::cout << s << "\n";
return 0;
}
/opt/gcc8/bin/g++ -std=c++1z a.cpp
In file included from a.cpp:5:
bra.txt:1:1: error: unterminated raw string
R"(
^
a.cpp: In function ‘int main()’:
a.cpp:4:27: error: expected primary-expression at end of input
constexpr const char* s =
^
a.cpp:4:27: error: expected ‘}’ at end of input
a.cpp:3:12: note: to match this ‘{’
int main() {
^
No, this cannot be done.
There is a c++2a proposal to allow inclusion of such resources at compile time called std::embed.
The motivation part of ths p1040r1 proposal:
Motivation
Every C and C++ programmer -- at some point -- attempts to #include large chunks of non-C++ data into their code. Of course, #include expects the format of the data to be source code, and thusly the program fails with spectacular lexer errors. Thusly, many different tools and practices were adapted to handle this, as far back as 1995 with the xxd tool. Many industries need such functionality, including (but hardly limited to):
Financial Development
representing coefficients and numeric constants for performance-critical algorithms;
Game Development
assets that do not change at runtime, such as icons, fixed textures and other data
Shader and scripting code;
Embedded Development
storing large chunks of binary, such as firmware, in a well-compressed format
placing data in memory on chips and systems that do not have an operating system or file system;
Application Development
compressed binary blobs representing data
non-C++ script code that is not changed at runtime; and
Server Development
configuration parameters which are known at build-time and are baked in to set limits and give compile-time information to tweak performance under certain loads
SSL/TLS Certificates hard-coded into your executable (requiring a rebuild and potential authorization before deploying new certificates).
In the pursuit of this goal, these tools have proven to have inadequacies and contribute poorly to the C++ development cycle as it continues to scale up for larger and better low-end devices and high-performance machines, bogging developers down with menial build tasks and trying to cover-up disappointing differences between platforms.
MongoDB has been kind enough to share some of their code below. Other companies have had their example code anonymized or simply not included directly out of shame for the things they need to do to support their workflows. The author thanks MongoDB for their courage and their support for std::embed.
The request for some form of #include_string or similar dates back quite a long time, with one of the oldest stack overflow questions asked-and-answered about it dating back nearly 10 years. Predating even that is a plethora of mailing list posts and forum posts asking how to get script code and other things that are not likely to change into the binary.
This paper proposes <embed> to make this process much more efficient, portable, and streamlined. Here’s an example of the ideal:
#include <embed>
int main (int, char*[]) {
constexpr std::span<const std::byte> fxaa_binary = std::embed( "fxaa.spirv" );
// assert this is a SPIRV file, compile-time
static_assert( fxaa_binary[0] == 0x03 && fxaa_binary[1] == 0x02
&& fxaa_binary[2] == 0x23 && fxaa_binary[3] == 0x07
, "given wrong SPIRV data, check rebuild or check the binaries!" )
auto context = make_vulkan_context();
// data kept around and made available for binary
// to use at runtime
auto fxaa_shader = make_shader( context, fxaa_binary );
for (;;) {
// ...
// and we’re off!
// ...
}
return 0;
}
I am working on a C++11 application that is supposed to ship as a single executable binary file. Optionally, users can provide their own CSV data files to be used by the application. To simplify things, assume each element is in format key,value\n. I have created a structure such as:
typedef struct Data {
std::string key;
std::string value;
Data(std::string key, std::string value) : key(key), value(value) {}
} Data;
By default, the application should use data defined in a single header file. I've made a simple Python script to parse default CSV file and put it into header file like:
#ifndef MYPROJECT_DEFAULTDATA
#define MYPROJECT_DEFAULTDATA
#include "../database/DefaultData.h"
namespace defaults {
std::vector<Data> default_data = {
Data("SomeKeyA","SomeValueA"),
Data("SomeKeyB","SomeValueB"),
Data("SomeKeyC","SomeValueC"),
/* and on, and on, and on... */
Data("SomeKeyASFHOIEGEWG","SomeValueASFHOIEGEWG")
}
}
#endif //MYPROJECT_DEFAULTDATA
The only problem is, that file is big. I'm talking 116'087 (12M) lines big, and it will probably be replaced with even bigger file in the future. When I include it, my IDE is trying to parse it and update indices. It slows everything down to the point where I can hardly write anything.
I'm looking for a way to either:
prevent my IDE (CLion) from parsing it or
make a switch in cmake that would use this file only with release executables or
somehow inject data directly into executable
Since your build process already includes a pre-process, which generates C++ code from a CSV, this should be easy.
Step 1: Put most of the generated data in the .cpp file, not a header.
Step 2: Generate your code so that it doesn't use vector or string.
Here's how to do these:
struct Data
{
string_view key;
string_view value;
};
You will need an implementation of string_view or a similar type. While it was standardized in C++17, it doesn't rely on C++17 features.
As for the data structure itself, this is what gets generated in the header:
namespace defaults {
extern const std::array<Data, {{GENERATED_ARRAY_COUNT}}> default_data;
}
{{GENERATED_ARRAY_COUNT}} is the number of items in the array. That's all the generated header should expose. The generated .cpp file is a bit more complex:
static const char ptr[] =
"SomeKeyA" "SomeValueA"
"SomeKeyB" "SomeValueB"
"SomeKeyC" "SomeValueC"
...
"SomeKeyASFHOIEGEWG" "SomeValueASFHOIEGEWG"
;
namespace defaults
{
const std::array<Data, {{GENERATED_ARRAY_COUNT}}> default_data =
{
{{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
{{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
...
{{ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}, {ptr+{{GENERATED_OFFSET}}, {{GENERATED_SIZE}}}},
};
}
ptr is a string which is a concatenation of all of your individual strings. There is no need to put spaces or \0 characters or whatever between the individual strings. However, if you do need to pass these strings to APIs that take NULL-terminated strings, you'll either have to copy them into a std::string or have the generator stick \0 characters after each generated sub-string.
The point is that ptr should be a single, giant block of character data.
{{GENERATED_OFFSET}} and {{GENERATED_SIZE}} are offsets and sizes within the giant block of character data that represents a single substring.
This method will solve two of your problems. It will be much faster at load time, since it performs zero dynamic allocations. And it puts the generated strings in the .cpp file, thus making your IDE cooperate.
Having worked quite long time with Unicode and C++ I thought this would be a simple thing to accomplish, especially with the new C++11 std::codecvt_utf8 facet. Though it turned out to be a diffcult task. What I want is to read a file encoded in UTF-8 into a u32string (converting it from UTF-8 to UTF-32 implicitly). Sure, I could load the entire content into a buffer and convert that using std::wstring_convert. But that doubles the memory footprint when loading a file. So I tried to use a std::wifstream and imbue a locale with a utf-8 facet like this:
std::wifstream stream(fileName, std::ios::binary);
stream.imbue(std::locale(stream.getloc(), new std::codecvt_utf8<char32_t, 0x10ffff, std::consume_header>));
std::u32string data;
for (char32_t c; stream >> c; )
data += c;
which looks like a straight forward implementation. It only doesn't compile. wifstream's element type is wchar_t, so you can only use wchar_t in the loop, like this:
std::u32string data;
for (wchar_t c; stream >> c; )
data += c;
(at least with clang, VC++ also accepts char32_t there, but that doesn't change anything). After fixing this several other problems remain, though:
In Visual C++ wchar_t is only 16bit (no UTF-32 then, we don't consider surrogate pairs here).
Using char32_t for the facet essentially disables conversion. The iteration over the stream returns the original UTF-8 content, both in clang and VC++.
Using wchar_t also for the facet makes it work in clang, but not in VC++, because in clang wchar_t is 32bit wide, while (as mentioned already) it is only 16bit in VC++.
So, what is the correct approach here? With the lock into wchar_t for the facet I cannot even use a different data type. I also tried defining a basic_ifstream<char32_t> but that requires additional typedefs, hence I didn't follow that path further.
Seems there is no way using a facet and imbue that in a stream, so I went with an intermediate buffer, which is a very elegant solution too, only that it doubles (more or less) the memory needed to load the content. Use a byte (file) stream in binary mode to call this:
void load(std::istream &stream)
{
static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utfConverter;
std::string s((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
_data = utfConverter.from_bytes(s);
}
Ive got a multi platform project that compiles great on mac, but on windows all my swprintf calls with a %s are looking for a wchar_t instead of the char * im passing it. Turns out M$ thought it would be funny to make %s stand for something other than char * in wide character functions... http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx
Anyways I'm looking for a creative coding trick thats better than putting ifdef else ends around every wide string call
Update: VS 2015 CTP6 reverted the changes and Microsoft are yet again acting different to the standard.
Visual Studio 14 CTP1 and later will always treat %s as a narrow string (char*) unless you define _CRT_STDIO_LEGACY_WIDE_SPECIFIERS. It also added the T length modifier extension which maps to what MS calls the "natural" width. For sprintf %Ts is char* and for swprintf %Ts is wchar_t*.
In Visual Studio 13 and earlier %s/%c is mapped to the natural width of the function/format string and %S/%C is mapped to the opposite of the natural with:
printf("%c %C %s %S\n", 'a', L'B', "cd", L"EF");
wprintf(L"%c %C %s %S\n", L'a', 'B', L"cd", "EF");
You can also force a specific width by using a length modifier: %ls, %lc, %ws and %wc always mean wchar_t and %hs and %hc are always char. (Documented for VS2003 here and VC6 here (Not sure about %ws and when it was really added))
Mapping %s to the natural width of the function was really handy back in the days of Win9x vs. WinNT, by using the tchar.h header you could build narrow and wide releases from the same source. When _UNICODE is defined the functions in tchar.h map to the wide functions and TCHAR is wchar_t, otherwise the narrow functions are used and TCHAR is char:
_tprintf(_T("%c %s\n"), _T('a'), _T("Bcd"));
There is a similar convention used by the Windows SDK header files and the few format functions that exist there (wsprintf, wvsprintf, wnsprintf and wvnsprintf) but they are controlled by UNICODE and TEXT and not _UNICODE and _T/_TEXT.
You probably have 3 choices to make a multi-platform project work on Windows if you want to support older Windows compilers:
1) Compile as a narrow string project on Windows, probably not a good idea and in your case swprintf will still treat %s as wchar_t*.
2) Use custom defines similar to how inttypes.h format strings work:
#ifdef _WIN32
#define PRIs "s"
#define WPRIs L"hs"
#else
#define PRIs "s"
#define WPRIs L"s"
#endif
printf("%" PRIs " World\n", "Hello");
wprintf(L"%" WPRIs L" World\n", "Hello");
3) Create your own custom version of swprintf and use it with Visual Studio 13 and earlier.
Use the %ls format which always means wchar_t*.
You can use "%Ts" format specifier or you can define _CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1.
Read this:
http://blogs.msdn.com/b/vcblog/archive/2014/06/18/crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1.aspx