0

I have a C library, which I'm not really allowed to modify in substantial way, that heavily uses the random function, which is not available on my Visual Studio 2010 compiler (see another one of my questions)

So, I have to write my own random method. I tried to use a simple random() { srand(time(NULL)); return rand(); } but the library main conceptor doesn't like it (he's on Mac and I think he doesn't care much about my problems). He tells me to run srand() only once when the library is run, but since there might be multiple entry points in this lib, I don't know how to do it. If you have a solution to this problem, I'm all ears.

Update: I have found out that the "main" function is always run during the loading of the library (from what I understand), so I'll use this for the seeding. But I'm still interested in the solution to this particular question.
Update 2: well, calling srand() from main() produces always the same results, so that's not the answer after all :(

So I decided to follow another method of generating random numbers:

#include <Windows.h>
#include <wincrypt.h>
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;
    }
}

But then I get this kind of error:

error LNK2019: unresolved external symbol __imp__CryptReleaseContext@8 referenced in the function _random

The problem, if I understand correctly, is that I'm calling C++ functions from C, and C doesn't understand the name mangling happening during C++ compilation.

I have visited the classic answer to calling C++ from C, but I didn't see a way to call a system C++ function from a C method. Is there something I've missed?

Thanks!

Community
  • 1
  • 1
thomasb
  • 5,816
  • 10
  • 57
  • 92
  • This was closed as a duplicate of a "what is an undefined reference?" question, but that doesn't make any sense. The question involves an undefined reference error, but it isn't asking what the error means. – Wyzard Jul 03 '14 at 13:02
  • so as not to put you on a wild goose chase checking out all possible causes of undefined reference in general, (1) find the documentation of the function mentioned in the error message, (2) in that documentation find which library provides it, (3) link in that library. – Cheers and hth. - Alf Jul 03 '14 at 13:03
  • BTW, if you just need a good PRNG, you could implement the [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_twister) in C, or find a C library that implements it already. That'd let you avoid having to call C++ functions, and it'd be portable across platforms too. – Wyzard Jul 03 '14 at 13:09
  • @Wyzard: the part that you left out, "and how do I fix it?", is the one that's relevant. – Cheers and hth. - Alf Jul 03 '14 at 13:09
  • @Cheersandhth.-Alf: Usually I see that the system requires five votes to close a question but how did you manage to do it single-handed? Just curious :) – legends2k Jul 03 '14 at 13:12
  • @Cheersandhth.-Alf, yes, but it's not "how do I fix undefined-reference errors?", it's "how do I call a function with a C++ mangled name from a C program?" The OP understands why calling it directly causes the linker error. – Wyzard Jul 03 '14 at 13:13
  • @Wyzard: have you tried the suggested solutions. – Cheers and hth. - Alf Jul 03 '14 at 13:15
  • @Cheersandhth.-Alf, I'm not the OP, but I've looked at the answers to the question you cited and none of them actually address this problem. The only one that even pertains to C++ name mangling is about calling a C function from C++ code without declaring it `extern "C"` on the C++ side, which is the complete opposite of what's happening here. – Wyzard Jul 03 '14 at 13:17
  • @Wyzard: the prefix `__imp__` in the error message is a dead giveaway about where this function stems from and what the problem is. you could have learned that by reading the duplicate's answers. instead of reading or asking you're arguing and wasting readers' time. – Cheers and hth. - Alf Jul 03 '14 at 13:25
  • Cheers: thanks for the simple and straightforward way for solving this issue (it would have helped me find the answer, had Constantin not provided it, because I found the missing lib referenced on the MSDN of the function). Wyzard: thanks for your support, but it actually turns out to be just a missing library. I actually don't need a *good* PRNG, it's absolutely not related to security, so a simple-and-dumb PRNG is enough. – thomasb Jul 03 '14 at 13:39
  • @Cheersandhth.-Alf, let's see, `__imp_` is mentioned… once, in the last paragraph of the fourth-ranked answer. Now that you've pointed it out, I see that the C++ name-mangling issue is a red herring, but I wouldn't have noticed that that answer was even relevant if you hadn't called attention to it. Your initial comment on this question is a pointer in the right direction but appears misguided to someone who's looking at the question from a name-mangling standpoint. – Wyzard Jul 03 '14 at 13:44
  • @Cheersandhth.-Alf, sorry for the lengthy debate — I've been thinking "WTF?" regarding the question's closure since before you posted your first comment. (I think it would've been more constructive to post that comment as an answer and mention `__imp_` as the sign that it's not actually a mangling issue.) – Wyzard Jul 03 '14 at 13:47

1 Answers1

3

Your problem seems to be something else: you have to link against Advapi32.lib to use the function CryptReleaseContext.

To do so:

Right click your project -> Properties -> Linker -> Input -> Additional Dependencies

Make sure, that Advapi32.lib is in the semicolon seperated list - otherwise add it there and rebuild your project. Then resolving the symbol __imp__CryptReleaseContext should be possible for your linker.

Constantin
  • 8,721
  • 13
  • 75
  • 126
  • Actually it was in the default list, but either re-adding it above the list, or selecting the "inherit" option made it work. It turns out that the code won't work with this function anyway (my best guess so far is that there is a reference/value problem) so I won't use it. Thank you ! :) – thomasb Jul 03 '14 at 13:32