-1

I am trying to get an unmanaged C++ DLL to work with my C# project, when running the program through debugger in VS2019 the code works. When running without debugger the app crashes when ran and event viewer gives me Exception Info: System.AccessViolationException when calling C++ Dll

I have tried changing the way I have used p/invoke with variations on what I have though might make it work. C++ isnt my forte but the DLL isnt anything complex and is just an if statement returning a string.

Is anyone able to see where I have gone wrong here? Or offer any tips on how to troubleshoot this issue?

C#

[DllImport("unmanaged.dll", EntryPoint = "checkCPU", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr checkCPU();

// to call it

 string check = Marshal.PtrToStringAnsi(checkCPU());

C++

extern "C" __declspec(dllexport) std::string checkCPU()
{

    if (InstructionSet::SSE41() || InstructionSet::SSE42()) {
        return "true";
    }
    else {
        return "false";
    }

}

(I know this has been asked a few times already, after rummaging round the internet I havent found anything that could help me.)

Edit

Both the DLL and project are x86, with the same netframework

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Francis L
  • 9
  • 1
  • Did you check that the program has access to the DLL file? By that I mean, is the DLL file in a location where the program can load it without needing any special permissions? Also, what are you trying to achieve by calling into native code and what are your reasons to do it? – MindSwipe Jan 29 '20 at 12:38
  • Returning a `std::string` from a DLL function will more than likely fail even if the language calling it is C++, let alone C#. The only way your function works is if the calling language is C++ **and**, the application calling your functions was built with the same C++ compiler using the same build options, **and** the runtime library used is the DLL version. – PaulMcKenzie Jan 29 '20 at 12:43
  • Possible duplicate of [std::string in C#?](https://stackoverflow.com/questions/874551/stdstring-in-c) – GSerg Jan 29 '20 at 12:52
  • @MindSwipe The program has access to the dll, its in the same directory. Basically the program is an audit tool, one of the requirements for the main program is that the users CPU supports the instruction set SSE4.1 - only realistic way I could think to acheive this is through use CPUID – Francis L Jan 29 '20 at 12:57
  • 1
    Stop returning types only known by `C++` such as `bool`. A `bool` in C++ is not the same as a `bool` in C#. A `bool` in C++ has a size determined by the compiler used. You should be using known types with known sizes that are agreed upon, such as `int32_t` (a 32-bit int), for example. – PaulMcKenzie Jan 29 '20 at 13:22
  • I reverted the question since your edit completely changed it and made a new question – David Heffernan Jan 29 '20 at 14:41

2 Answers2

0

Thanks all for your comments, actually down to me being a bit dumb.

C++ needed to be BOOL and not bool.

c# was fine being bool.

Now have a new problem but progress.

Thanks again.

Francis L
  • 9
  • 1
-1

You can't return a C++ object like std::string using pinvoke. There are a variety of options available to return text to the caller using pinvoke:

  1. Return a COM BSTR.
  2. Return a C string, allocated by the callee. The caller will need to deallocate it. Either by using a shared heap, or by exporting a deallocator function.
  3. Have the caller allocate the text buffer, and let the callee populate it.

Examples of all of these approaches can be found readily by websearch.

I'm assuming that your code is a simplified example, but if you really want to indicate just success or failure, then you can completely side-step the issue by returning a boolean type.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490