2

I'm calling a DLL from both C# and C++. The goal is to establish a connection with a hardware prototype. If I call the DLL Method using C++ the connection is established! But I've to call the function using C# for various reasons.

How is it possible to get two different responses from the same method? The only difference is the programming language the method gets called from...

I'm thankful for every suggestion!

Here is the definition of the method to be called:

extern "C" __declspec(dllexport) bool establishCon()
{
    LL_Init();
    return establishConnection();
}

The the Method gets called in C++ in the following way:

HMODULE dll = LoadLibrary(L"LL_Controll.dll");
if (dll != NULL)
{
    establishCon est = (establishCon)GetProcAddress(dll, "establishCon");
    if (est != NULL)
    {
        bool res = est();
        if (res == true)
        {
            printf("Worked");
        }
        else
        {
            printf("Failed!");
        }
    }
    else
    {
        printf("Problem!");
    }
}
else
{
    printf("CantLoadDLL");
}

The C++ Call returns true!

In C# the method gets called in the following way:

[DllImport(@"D:\C\2018-02-21\OccupancyTest01\x64\Debug\LL_Controll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern bool establishCon();

public bool call_LL_Controll_estabCon()
{
    return establishCon();
}

In this case false is returned.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • It is rather important to clarify if you mean native C++ or C++ .NET. C++ .NET is closer to C# then to native C++. – Christopher Apr 05 '18 at 13:34
  • see this explanation [https://stackoverflow.com/questions/315051/using-a-class-defined-in-a-c-dll-in-c-sharp-code](https://stackoverflow.com/questions/315051/using-a-class-defined-in-a-c-dll-in-c-sharp-code) – Binu MD Apr 05 '18 at 13:41
  • It should be native c++! – Simon SCHÖNEGGER Apr 05 '18 at 14:05
  • Sounds like an [XY Problem](http://xyproblem.info/) to me. Probably the _content_ of your `establishCon()` (i.e. the call to `LL_Init();`, `return establishConnection();` etc.) behaves different because of the context/environment it is being called from (thus resulting in different return values) and _not_ because of the language being called from. I would first let `establishCon()` return a constant `true`/`false` and see whether these results work the same in both calling languages. – Uwe Keim Apr 05 '18 at 14:06
  • @UweKeim Both calling languages are returning the same result if I use constant values. – Simon SCHÖNEGGER Apr 05 '18 at 14:12
  • @SimonSCHÖNEGGER Perfect! So you should start investigating, what `LL_Init();` and `return establishConnection();` assumes regarding the environment it is being called from and then fix these issues. – Uwe Keim Apr 05 '18 at 14:13
  • @UweKeim Thanks, I will try to do that. I'm working with an API as a part of a project regarding a hardware prototype. The DLL I mentioned above is just a wrapper-like context for the real API. I chose work that way, because C# can't handle callbackfunctions, etc. that well and I don't have to replicate pointers. So the DLL communicates with the API, sets all the callbacks etc. – Simon SCHÖNEGGER Apr 05 '18 at 14:19

2 Answers2

0

I don't have a Windows dev rig handy to test with, but can you try the following?

[DllImport(@"D:\C\2018-02-21\OccupancyTest01\x64\Debug\LL_Controll.dll", CallingConvention=CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool establishCon();

Boolean types are a bit tricky to C#-interop with. YMMV, but adding an explicit 1-byte marshalling directive for the returned type did the trick for me, in past projects.

More info: https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/

  • Please see [the above comments](https://stackoverflow.com/questions/49673494/c-sharp-vs-c-dll-call?noredirect=1#comment86359551_49673494). It is _not_ about the return values but actually about the content of the function being called. – Uwe Keim Apr 05 '18 at 14:32
  • @UweKeim Nonetheless, this is clearly a common pitfall that the OP needs to learn about. – OldFart Apr 05 '18 at 14:43
  • 1
    @OldFart Probably he should also learn how to iron his clothes, I guess? – Uwe Keim Apr 05 '18 at 14:46
-1

There are 3 basic cases when interacting with a DLL from .NET:

  1. It is a .NET DLL. So it is programmed into the IL format of .NET. This is the simplest case: You add a project reference. Intellisense and Autocomplete will get all the public namespaces and types like they already do for every other reference DLL. Moreover, .NET exe can be used as DLL's. The internal format is pretty similar, aside from some native Bootstrapping code and a manifest that tells the Runtime "wich class has the main function" it is mostly the same as a .NET DLL
  2. It is a COM enabeled DLL. COM (https://en.wikipedia.org/wiki/Component_Object_Model) is in several points a predecessor of .NET and as such there is really strong interop in both ways (https://en.wikipedia.org/wiki/COM_Interop). .NET can relatively easily use COM dll's. And .NET DLL's expose everything needed to use them like COM ones.
  3. The ultimative fallback is P/Invoke. That is what you use whenever you have to deal with any Native Code, like some age old Windows API functions or native code.
Christopher
  • 9,634
  • 2
  • 17
  • 31
  • 1
    How is this an answer to the question? – Uwe Keim Apr 05 '18 at 13:44
  • @UweKeim: It was to big/complicated for a Comment. So I had no other choice. Plus actually clearly differentiating between those 3 cases and wich one precisely you have is rather important for Debugging. You can not expect COM Interop to behve the same as P/Invoke as each one has their own Idiosincracies born from Decades old Decisions. – Christopher Apr 05 '18 at 13:57
  • 1
    I don't understand why this is worth a comment, either? From my understand, it doesn't help the OP in any way. Neither as an answer, nor as a comment. – Uwe Keim Apr 05 '18 at 14:03