Following my previous question here : Compile a C library with Visual Studio 2010 ; I have a C project, with a source file I can't meaningfully change.
After fixing the previous problem, I now have two more errors:
error LNK2019: unresolved external symbol _random referenced in the function _fisher_yates myfile.obj
error LNK1120: 1 unresolved external myproject.dll
The line refering to _random
is this:
j = i + random() % (nb - i);
I'm guessing that random()
is not part of the standard C/C++ libraries ?
A colleague has suggested looking at the makefile for the included libraries to see what would be missing. I have found this:
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
and a bit further:
LIBS = $(LIBRUBYARG_SHARED) -lshell32 -lws2_32 -limagehlp -lshlwapi
At the top of my c file, I have added:
#ifdef _MSC_VER
#define inline __inline
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "imagehlp.lib")
#pragma comment(lib, "shlwapi.lib")
#endif
But I still get the same error, so I guess it's the LIBRUBYARG_SHARED
that's the cause of the problem. I don't even know what it is ; the makefile is generated through 'mkmf'.
As you may notice, I have no idea what's going on, and any help is appreciated.
Thanks !
Update
In the #ifdef _MSC_VER
section I have added a #define random rand
instruction. While rand() is not safe, this has nothing to do with security (it's to shuffle objects on screen), so I think it will be enough.
Update 2
Actually just "binding" random to rand is not enough, because rand returns always the same value if not used with srand. So, following this article, I have written my own random() function:
#ifdef _MSC_VER
// fix: the Visual Studio 2010 C compiler doesn't know "inline" but knows "__inline".
// see: https://stackoverflow.com/a/24435157/2354542
#define inline __inline
#include <Windows.h>
#include <wincrypt.h>
/// Visual C++ 2010 is not POSIX compliant :'( so I have to code a random() method
/// https://www.securecoding.cert.org/confluence/display/seccode/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers
long int random() {
HCRYPTPROV prov;
if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
long int li = 0;
if (CryptGenRandom(prov, sizeof(li), (BYTE *)&li)) {
return li;
} else {
// random number not generated
return 0;
}
if (!CryptReleaseContext(prov, 0)) {
// context not released
return 0;
}
} else {
// context not created
return 0;
}
}
#endif
See Question&Answers more detail:
os