0

I have a C source file that is automatically generated from some data:

#include <stdint.h>
size_t BlurKernel_size = 840;
unsigned char BlurKernel[] = {
0x06b, 0x65, 0x72, // ... etc
};

I compile it to an object file using

cl /nologo kernels_embedd.c /c /Fokernels_embedd.obj /W4 /O2 /MT

Then put it into a static library

lib /nologo /OUT:kernels_embedd.lib kernels_embedd.obj

Then I link it with my main program (which does extern const char* BlurKernel; extern const size_t BlurKernel_size;):

link /nologo /OUT:main.dll /DLL main.obj kernels_embedd.lib /IMPLIB:main.lib

And I get the error

main.obj : error LNK2019: unresolved external symbol "char const * const BlurKernel" (?BlurKernel@@3PEBDEB) referenced in function "public: __cdecl BlendIop::BlendIop(class Node *)" (??0BlendIop@@QEAA@PEAVNode@@@Z)
main.obj : error LNK2019: unresolved external symbol "unsigned __int64 const BlurKernel_size" (?BlurKernel_size@@3_KB) referenced in function "public: __cdecl BlendIop::BlendIop(class Node *)" (??0BlendIop@@QEAA@PEAVNode@@@Z)
main.dll : fatal error LNK1120: 2 unresolved externals

However, looking at kernels_embedd.lib with dumpbin, the symbols are available:

> dumpbin kernels_embedd.lib /symbols
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file kernels_embedd.lib

File Type: LIBRARY

COFF SYMBOL TABLE
000 00AA766F ABS    notype       Static       | @comp.id
001 00000000 SECT1  notype       Static       | .drectve
    Section length   45, #relocs    0, #linenums    0, checksum        0
003 00000000 SECT2  notype       Static       | .debug$S
    Section length   CC, #relocs    0, #linenums    0, checksum        0
005 00000000 SECT3  notype       Static       | .data
    Section length  358, #relocs    0, #linenums    0, checksum ABAE4B9B
007 00000000 SECT3  notype       External     | BlurKernel_size
008 00000010 SECT3  notype       External     | BlurKernel

String Table Size = 0x1F bytes

  Summary

        358 .data
          CC .debug$S
          45 .drectve

(I get the same output when looking at kernels_embedd.obj with dumpbin).

I have successfully used this method with GCC before. What am I doing wrong with MSVC?

Niklas R
  • 16,299
  • 28
  • 108
  • 203
  • Make it `extern "C" { extern const char* BlurKernel; extern const size_t BlurKernel_size; }` The linker is looking for `?BlurKernel@@3PEBDEB` symbol (the C++ mangled name), but what's available is `BlurKernel` symbol. [`extern "C"`](https://msdn.microsoft.com/en-us/library/s6y4zxec.aspx) suppresses name mangling. – Igor Tandetnik Jan 04 '18 at 16:08
  • Is `/IMPLIB:main.lib` a typo? I thought your static library was called `kernels_embedd.lib`. – Ian Abbott Jan 04 '18 at 16:10
  • @IgorTandetnik Aha! I see the issue now. Thank you, that works! – Niklas R Jan 04 '18 at 16:11
  • @IanAbbott `/IMPLIB` specifies the name of the DLL's Import Library (which defaults to `.lib`, so the argument would be redundant in this case). On windows you have a separate `.lib` file even if you want to link to a shared library. – Niklas R Jan 04 '18 at 16:12
  • @NiklasR Yes, I should have checked what `/IMPLIB` actually does! Glad you got it working anyway. So where does `kernels_embedd.lib` get linked in? Should the `kernels_embedd.obj` in the `link` command actually be `kernels_embedd.lib`? – Ian Abbott Jan 04 '18 at 16:16
  • @IanAbbott Ah yes, now *that* is indeed a typo. Thanks for the headsup. – Niklas R Jan 04 '18 at 16:32
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?: Symbols were defined in a C program and used in C++ code](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix/12574420#12574420) – Raymond Chen Jan 04 '18 at 22:02

1 Answers1

2

As @IgorTandetnik pointed out, the symbols need to be externed in C-fashion to avoid C++ name-mangling.

extern "C" unsigned char BlurKernel[];
extern "C" size_t BlurKernel_size;

An important side note, to correct a mistake in the question: BlurKernel was defined as an array, thus it is important to extern it as such. Using unsigned char* BlurKernel does not work (results in access violation when the pointer is dereferenced).

Niklas R
  • 16,299
  • 28
  • 108
  • 203