13

UPDATED: Added what RoInitialize looks like in roapi.h

I am in the process of writing a pure C++11 WinRT library. I do not use WRL or C++/CX (Obviously if I want pure C++11).

I got my code to compile and run on MSVC, but I want to see if I can get the code to compile and run on Mingw Gcc. Specifically, I am using GCC 4.7.2 obtained from nuwen.net.

What I need at this point is a way to call the Windows API Functions RoInitialize, RoUnitialize, RoGetActivationFactory and the HSTRING Functions WindowsCreateString, WindowsDuplicateString, WindowsDeleteString.

I tried compiling this program in G++ but got the error

extern "C"{
__declspec(dllimport)int __stdcall RoInitialize(int);
}
int main(){
    RoInitialize(1);
}

I tried to compile but got:

c:\Users\jrb\Desktop>g++ gccwinrt.cpp
C:\Users\jrb\AppData\Local\Temp\ccy7y1V9.o:gccwinrt.cpp:(.text+0x1e): undefined
reference to `_imp__RoInitialize@4'
collect2.exe: error: ld returned 1 exit status

If anybody can point me in the right direction on how to declare these functions and what libraries I need to link to, I would appreciate it. Even if it requires LoadLibrary/GetProcAddress I would still be ok with that

Update: Here is what RoInitialize looks like in the header roapi.h

ROAPI
_Check_return_
HRESULT
WINAPI
RoInitialize(
    _In_ RO_INIT_TYPE initType
);

ROAPI is just a define for __declspec(dllimport)
_Check_return_ is part of SAL (Secure Annotations Language?)
HRESULT maps to int32
WINAPI is a define for __stdcall
RO_INIT_TYPE is an enumeration so int should cover it
Ajay
  • 18,086
  • 12
  • 59
  • 105
John Bandela
  • 2,416
  • 12
  • 19
  • Forgive me if something changed, but is just including the header and using the function not enough? – chris May 09 '13 at 16:35
  • 1
    What happens if you include Roapi.h? How does the declaration look in this header? – Tadeusz Kopec for Ukraine May 09 '13 at 16:39
  • These functions are Windows 8 only. The headers are not available in mingw gcc. Also, even if I used the headers from Visual C++, I would still have to link to the correct import library which Mingw gcc does not have for these functions – John Bandela May 09 '13 at 16:40
  • 1
    Oh, I see. This is why I use Visual Studio for Windows Vista+ APIs. I don't see a DLL, though, which kind of sucks, since it's not that hard to make something to easily call a function in a DLL. – chris May 09 '13 at 16:44
  • @TadeuszKopec I get that Gcc can't find the include file. I have updated the question to show the excerpt from the header – John Bandela May 09 '13 at 16:47

4 Answers4

18

The import library for these functions is runtimeobject.lib (which the MSDN documentation fails to mention). It can be found in the Windows SDK for Windows 8.

Jakub Berezanski
  • 1,053
  • 9
  • 13
7

The library you need to link against is windowsapp.lib (and only this lib, remove all others).

This topic lists the Win32 APIs that are part of the Universal Windows Platform (UWP) and that are implemented by all Windows 10 devices. For convenience, an umbrella library named WindowsApp.lib is provided in the Microsoft Windows Software Development Kit (SDK), which provides the exports for this set of Win32 APIs. Link your app with WindowsApp.lib (and no other libraries) to access these APIs.

APIs present on all Windows 10 devices - Microsoft Docs

See that page for a complete list of functions that implements; it includes RoInitialize, RoUnitialize, RoGetActivationFactory and WindowsCreateString, WindowsDuplicateString, & WindowsDeleteString (among many, many others). If you need other functions, you may need to link extension APIs also.

Similar guidance was originally on https://msdn.microsoft.com/en-gb/windows/uwp/get-started/universal-application-platform-guide#writing-code but is no longer present:

Windowsapp.lib is an "umbrella" lib that provides the exports for the UWP APIs. Linking to Windowsapp.lib will add to your app dependencies on dlls that are present on all Windows 10 device families.

For delay loading, you will need to load api-ms-win-core-winrt-l1-1-0.dll, which is an API set, a collection of APIs that Windows can load regardless of where the actual DLLs are. This specific set is listed as a Windows 8.1 API set, however if you check the documentation for RoInitialize it says the minimum supported client is Windows 8. Assuming you use LoadLibrary and GetProcAddress, it shouldn't matter.

The actual DLL that the method is implemented in is combase.dll, but they use these API set DLLs as a level of indirection so that they are free to change or update that original DLL in the future.

For future reference, the API sets for Windows 10 (UWP) are listed on a separate page to the API sets for Windows 8 (and 8.1). The stub DLL (for delay loading) is the same. https://msdn.microsoft.com/library/windows/desktop/mt186421

Many other APIs also list their corresponding API set in their own documentation. For example, MSDN gives AllowSetForeground as an example.

citelao
  • 4,898
  • 2
  • 22
  • 36
Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
0

If you don't have the import lib that contains RoInitialize, you'll need to use LoadLibrary/GetProcAddress to resolve the types.

Larry Osterman
  • 16,086
  • 32
  • 60
  • 2
    Very helpful answer! And in which DLL are these functions ? You are missing the most important part! – Elmue Aug 21 '15 at 13:24
  • 1
    The dll that those reside in is `api-ms-win-core-winrt-l1-1-0.dll`: https://msdn.microsoft.com/en-us/library/windows/desktop/dn933214%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 – c00000fd Oct 03 '16 at 04:20
0

Run-time link it like this:

#include <roapi.h>

namespace
{
    FARPROC LoadComBaseFunction(const char* function_name)
    {
        static HMODULE const handle = ::LoadLibraryA("combase.dll");
        return handle ? ::GetProcAddress(handle, function_name) : nullptr;
    }

    decltype(&::RoInitialize) GetRoInitializeFunction()
    {
        static decltype(&::RoInitialize) const function = reinterpret_cast<decltype(&::RoInitialize)>(LoadComBaseFunction("RoInitialize"));
        return function;
    }
}


HRESULT RoInitialize(RO_INIT_TYPE init_type)
{
    auto ro_initialize_func = GetRoInitializeFunction();
    if (!ro_initialize_func)
        return E_FAIL;

    return ro_initialize_func(init_type);
}

Source

DJm00n
  • 1,083
  • 5
  • 18