Search code examples
cwindowswinapicygwin

Compile & link static library calling winapi under cygwin


I have a project in C which I am porting to from unix/linux to Windows/Cygwin (using autotools). I need to call some winapi functions. These functions require inclusion of some windows headers. But when I specify those includes a lot of errors caused by redefinition of some structs or functions are raised.

So I decided to create a static library where all winapi function will be called to avoid these errors. But i have some difficulties getting it work.

For now the static library contains only one call of winapi function GetAdaptersAddresses and looks like this:

#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>

void win_if_scan(void)
{
  ULONG size = 10 * sizeof(IP_ADAPTER_ADDRESSES);
  IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)malloc(size);

  GetAdaptersAddresses(AF_INET,
    GAA_FLAG_INCLUDE_ALL_INTERFACES |
    GAA_FLAG_INCLUDE_PREFIX |
    GAA_FLAG_SKIP_DNS_SERVER,
    NULL,
    addresses,
    &size);
}

and I am compiling the library libwin.a like this:

gcc libwin.c -liphlpapi -o libwin.o
ar crv libwin.a libwin.o

From the project I call the win_if_scan function (and I include header for the libwin). But I got error: undefined reference to WinMain, full message is:

$ make > /dev/null
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/../../../../lib/libcygwin.a(libcmain.o): In function `main':
/usr/src/debug/cygwin-1.7.33-1/winsup/cygwin/lib/libcmain.c:39: undefined reference to `WinMain'
/usr/src/debug/cygwin-1.7.33-1/winsup/cygwin/lib/libcmain.c:39:(.text.startup+0x7e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
make[1]: *** [libwin.o] Error 1
make: *** [all] Error 2

I don't understand what is happening here. It is a library, why it requires main function? When I tried to add:

int main(void) { return 0; }

or

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { return 0; }

it indeed says multiple definition of main as expected.

How to get this work? Or is there a better way how to handle redefinition errors between cygwin & windows headers?


Solution

  • First step is to generate only object file from libwin as I mentioned in the comment. Second, the specification of the library -liphlpapi must go where the project is linked together, not where the object file is generated. Which makes sense since no linkage is done there. So the library archive is created by following commands:

    gcc -c libwin.c -o libwin.o
    ar crv libwin.a libwin.o
    

    and the project is linked together like this:

    $(exedir)/bin: $(bin-dep)
        $(CC) $(LDFLAGS) -o $@ $^ ../libwin/libwin.a $(LIBS) -liphlpapi
    

    which is a Makefile rule, where you can see where I added the ../libwin/libwin.a and -liphlpapi

    This is still a work in progress, so sorry for not very nice or systematic solution, but the idea is there.

    Important thing to have on mind is also location of the -liphlpapi in the Makefile rule as mentioned a here