UWP - Suggested way for reusing string parsing functions across WinRT modules - c++

I have a number of C++ projects in my solution that were written by other teams before I started working on my UWP app, and all of these projects use std::strings. So, to ease the communication between the other projects and my WinRT modules, I wrote some string conversion functions to go from std::strings to Platform::Strings and vice versa.
I'm in the process of converting my UWP codebase into WinRT modules and I'm coming across a recurring problem: because WinRT modules don't allow you to have classes or functions with public native types, I am unable to have my string functions publicly accessible. A private, protected, or internal declaration is fine for passing around native types, just not public.
Many of my modules need to communicate down into the native C++ code and I don't want to have to redefine my string functions again and again for each individual file that needs a std::string.
Is there anything I can do so I can reuse my string functions across WinRT modules? Has anyone else had a similar problem? Any suggestions are greatly appreciated!
Thank you

You have two options.
Make those functions inline, and define all of them in a header file. Then, include the header file everywhere you want to consume them. This is a more straightforward solution without requiring you to mess with your build system.
You can compile those functions into one of your DLLs, and import them to other ones. Let's call the DLL where you put your functions in "StringModule.dll". You'll need to put those functions in a .cpp/.h header file pair, then compile that .cpp file into StringModule.dll. Then, annotate your functions with a define that evaluates to __declspec(dllexport) when building StringModule.dll, and __declspec(dllimport) when building all the other DLLs. For instance:
#ifndef BUILDING_STRING_CONVERSIONS_DLL // This should be defined to 1 when building StringModule.dll
#define BUILDING_STRING_CONVERSIONS_DLL 0
#endif
#if BUILDING_STRING_CONVERSIONS_DLL
#define MY_STRING_API __declspec(dllexport)
#else
#define MY_STRING_API __declspec(dllimport)
#endif
namespace MyStringFunctions
{
MY_STRING_API Platform::String^ ConvertStdStringToPlatformString(const std::string& str);
MY_STRING_API std::string ConvertPlatformStringToStdString(Platform::String^ str);
}
When you build StringModule.dll, there will be StringModule.lib file created next to it. You'll have to pass its path to the linker as an argument when building all the DLLs that consume your string functions. In all the places where you want to use your DLL, just include that header file and use them as usual.

Related

How do I resolve naming conflicts with headers that use the preprocessor to redefine common function names?

EDIT: I found a similar question, and the answers are basically that windows.h is bad and you must either rename your functions or #undef the macros: Other's library #define naming conflict
However, I believe mine is still different due to the conflicting behavior of LoadLibrary under debug and release builds.
I am programming on Windows using Visual Studio and I ran into a few peculiar issues with preprocessor directives used by windows.h and the headers it includes.
Our project had a function in its own namespace, MyProject::FileManager::CreateFile(). After including windows.h our code failed to compile due to a linker error stating that it could not resolve MyProject::FileManager::CreateFileW (note the W at the end of the function name). This was not a static function, it was a member function of a FileManager object that was being called with file_manager.CreateFile(...).
When highlighting the function in Visual Studio a tooltip displayed the following:
#define CreateFile CreateFileW
We were puzzled but just renamed the function as a workaround. However later we ran into a similar issue with the LoadLibrary function we were trying to use from the Windows API. Compiling in Debug mode, LoadLibrary was defined as LoadLibraryW() which took an LPCWSTR (wide string) as a parameter. When I tried building in Release mode this function was now defined as LoadLibraryA() which takes a normal LPCSTR. This broke our build because the code was written under the assumption that LoadLibrary took an LPCWSTR.
So, my question is, how should a programmer deal with this? Should I just wrap my calls to LoadLibrary with #ifdef's checking for Debug or Release mode? Or is there a more simple solution?
Also, I found an interesting header file on github which appears to have been created for the sole purpose of #undef'ing all these function names:
https://github.com/waTeim/poco/blob/master/include/Poco/UnWindows.h
There are few things I generally do to cope with this:
Isolate all Windows system calls in a Windows-specific layer. For example, if I'm working with the file system API, I'll typically have win/filesystem.h and win/filesystem.cpp to wrap all the calls. (This is also a good place to convert Win32 errors into std::system_error exceptions, remove unneeded/obsolete/reserved parameters, and generally make the Windows API more C++ friendly.)
Avoid using Windows-specific types. Allowing definitions like DWORD, LPTSTR and BOOL to infiltrate all levels of your code makes dealing with Windows.h that much more difficult. (And porting too.) The only files that should #include <Windows.h> should be your wrapper C++ files.
Avoid using the Windows redirection macros yourself. For example, your wrapper layer should call CreateFileW or CreateFileA directly instead of relying on the macro. That way, you don't need to depend on the Unicode/Multi-byte project setting.
Example
win/filsystem.h might contain definitions like this:
namespace win32
{
class FileHandle
{
void* raw_handle_;
public:
// The usual set of constructors, destructors, and accessors (usually move-only)
};
FileHandle CreateNewFile(std::wstring const& file_name);
FileHandle OpenExistingFile(std::wstring const& file_name);
// and so on...
}
Any part of your code can include this file to access the file system API. Since win/filesystem.h does not itself include <Windows.h>, the client code will be uncontaminated by the various Win32 macros.
The problem here is that windows.h tries to support two different string models: strings consisting of single-byte characters and strings encoded in unicode (defined by microsoft as two-byte characters). Almost all of the Windows API functions have two different versions, one that takes single-byte character strings and one that takes two-byte character strings. You're supposed to write your code with the generic names (such as CreateFile, LoadLibrary, etc.) and let windows.h take care of mapping those names to the actual API functions. For single-byte characters those two are CreateFileA and LoadLibraryA; for two-byte characters they are CreateFileW and LoadLibraryW. And there are a bajillion more, of course. You choose the model at compile time by defining the macro UNICODE in every compilation unit.
Incidentally, the 'A' suffix stands for "ANSI", and the 'W' suffix stands for "wide character".
This is particularly insidious when you write code that tries to isolate the Windows dependencies into a handful of source files. If you write a class that has a member function named CreateFile, it will be seen in source files that don't use windows.h as CreateFile, and in source files that do use windows.h as CreateFileA or CreateFileW. Result: linker errors.
There are a several ways around this problem:
always #include <windows.h> in every header file; that's a compiler performance killer, but it will work. (windows.h was a major motivator for precompiled headers in early C++ compilers targeting windows)
always use the doctored name, either CreateFileA or CreateFileW; that will work, but at the cost of losing the flexibility of being able to change the underlying string model when you're making API calls; whether that matters is up to you.
don't use any of the Windows API names; potentially painful if you use the same naming convention as Windows; not at all painful if you use snake case, i.e., all lower-case with underbars to separate words. For example, create_file. Alternatively, use a local prefix or suffix: MyCreateFile or CreateFileMine.

Reason for "{return 0;}" or "{;}" in library's .h file

I am currently working on a project with some old poorly documented code, and am trying to navigate my way through the various .h files that they have provided complete documentation on the use of all of the functions contained (the definitions are held in .lib and .dll files). One of the .h files has functions the are not only declared, but defined with either simple return statements or empty statements as such
class DLL ExampleLibraryClass {
public:
int exampleGetValue() {return 0;}
void exampleSetValue(Type val) {;}
void exampleActionFxn() {;}
};
These would be functions that I expect to return current variable states or perform certain actions, which is why this puzzles me.
Additionally:
I have used Dependency Walker and found that each function does have a matching definition in a dll.
The Keyword DLL has been defined with
#ifndef _PWSDLL_
# define _PWSDLL_
# define WINCALL _stdcall
# ifdef _USRDLL
# define DLL __declspec(dllexport)
# else
# define DLL __declspec(dllimport)
# endif
#endif
_USRDLL is not defined and therefore DLL is defined as __declspec(dllimport)
My question revolves less about the apparent effect of the empty definitions (which do nothing I suppose, and have already been discussed on SO) and more about why the .h file has been written this way and how to utilize the file. Is this a common or known practice? Will the linker still look for definitions to the function in my linked libraries? Are there other pieces of code that I should look for for more clues? Or perhaps in the broadest sense, how should I respond to this?
Many thanks, and please let me know if you need more information to address this, I am unsure what exactly is important in this matter.
EDIT: Added forgotten return types in example code.
EDIT: Added note about DLL definition.
One scenario where you put this code to some use would be to override the functions. These functions hold some default code and could be overridden later.

Where to define error code constants in C++

I have exported a method from a C++ DLL and then call it from a VB.net forms application. The C++ method currently has no return value (void) but I want to improve it and return an int that represents a series of error codes. (I plan to return zero if all went well.)
Where and how is the best place to define these error codes?
Should I do the following at the top of my CPP file:
#define ERR_NEGATIVE_CELL_SIZE 1
#define ERR_INVALID_FILE_PATH 2
etc
The VB.net application will also define these same codes and then show UI messages to the user based on the code.
Obviously I would prefer to throw an exception in the DLL and catch it (along with the relevant exception message) in VB.net, but this doesn't seem to be possible using the extern "C" __declspec(dllexport) method.
Happy to hear about alternative design patterns. I also plan to expose the DLL methods via a C++ console executable, so storing the error messages once in the DLL and having them available to both the console and UI applications is ideal.
If you want the error codes to be available to other compilation units then they are best placed in a header file. Typically when writing library code you would create one or more header files that declare all the constants, types, functions and classes that are needed to use the library. The implementations are then compiled into the library. The consumer of the library includes your headers and an import library.
Regarding your constants, you are proposing using #define to declare them. Don't do that. Consider using constants or enums. The pre-processor is generally something to use as little as possible.
Please avoid the preprocessor wherever possible.
For your scenario, defining an enum would be reasonable.
Define it next to the function prototype.
For exposing the translations, use a translation function and export that too.
Something like:
size_t TranslateError(int error, char* buffer, size_t size)
Returns: size of the translated message, message in the buffer if return <= len

Exporting functions from a DLL using __declspec(dllexport)

I 'm working on a project (VS 2012 solution) including joystic.cpp. Project has been created as DLL, in order to be able to call library from another project. The application receives immediate joypad data in exclusive mode via a dialog timer, displaying them in a dialog box.
I edited the resource.h file with macro:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
in order to be able to export functions by ordering:
LIBRARY_API function();
However, should I export all functions of the program, or not?
Should I export all functions of the program, or not?
Generally when designing the interface to a library, you should export just the functions that are needed by consumers of the library.
If you exported every function then you would need to document every function. However, many functions may not be needed by library consumers. Many functions will be private to the implementation of the library.
What's more, by exporting all functions you would be making future development of the library more difficult. What if you wanted to change the interface to one of these private functions that you exported? You would have to either introduce another function with a different name, or use the existing name and so break binary backwards compatibility. Neither of these options is particularly appealing.
In essence, the larger the surface area of your library's public interface, the larger your maintenance task. So you generally aim to provide the smallest possible public interface that provides the required functionality to library consumers.

A variable across the whole application

I have a C++ windows application which is composed of several DLLs.
I want to have some sort of a pool from which I'll get objects, but in a way that this pool
would be available in all the DLLs.
So I put it in a "Common" dll which everbody has access to and defined it in a header file like so:
static Pool globalPool;
I do have access from every dll but this pool is created many many times.
I think it happens in each of my DLLs and in each File which include the header file with the definition.
How can I do it properly?
thanks :)
A static declaration of an object makes the object local to the compilation unit.
By using static you're creating a globalPool object (variable) in every compilation unit where you include the header.
But the way to do what you want is not to just remove the static.
Instead define a function providing access to your pool (e.g. a reference to it), and export that function or set of functions from the pool DLL.
Or better -- much better -- forget the idea. It's a generally bad idea. However, if you really want to do it, and can't see any alternative, then above is how to do it.
And if you do that, perhaps think about thread safety.
And perhaps be aware that dynamic loading of Windows DLLs does not work well with compiler support for thread local variables.
Cheers & hth.,
In the header file you need
extern Pool globalPool;
Then in a .cpp file in the Common dll, you need
Pool globalPool;
The extern declaration will put it in the namespace of including modules, and the linker will resolve it to the object in the common dll.
You'll want a header file that looks something like this:
// Common.h
#pragma once
#ifdef COMMON_BUILD
// When building Common.dll, want to export the definition of Pool
#define COMMON_EXPORT __declspec(dllexport)
#else
// When using Common.dll, want to import the definition of Pool
#define COMMON_EXPORT __declspec(dllimport)
#endif
// Declarations of shared globals
struct COMMON_EXPORT Pool {
static int data1;
static int data2;
};
(For more about the dllimport and dllexport stuff, see http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx and http://msdn.microsoft.com/en-us/library/81h27t8c.aspx)
Then in your DLL's build, you will want a source file like this:
// Common.cpp
#define COMMON_BUILD
#include "Common.h"
int Pool::data1 = 0;
int Pool::data2 = 0;
Then, all the DLLs and EXEs that use it should "#include Common.h" and link with the Common DLL, and then they can use Pool::data1, etc.