CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Thread: DLL C++ and C#

  1. #1
    Join Date
    May 2020
    Posts
    3

    DLL C++ and C#

    Hi,

    I'm writing a dll in C++ to get the serial hd, this is the code of the function:
    Code:
    __declspec(dllexport) char* __stdcall char* GetSerialHD()
    {
         WmiQueryResult res = getWmiQueryResult(L"SELECT SerialNumber FROM Win32_PhysicalMedia", L"SerialNumber");
         char* ret = NULL;
         std::string strValue;
         char* strReturn = NULL;
         for (const auto& item : res.ResultList) {
              strValue.assign(item.begin(), item.end());
              ULONG ulSize = strlen(MyString) + sizeof(char);
              strReturn = (char*)::CoTaskMemAlloc(ulSize);
              strcpy(strReturn, strValue.c_str());
              break;
         }
         return strReturn;
    }
    The dll function calls it from an application written in C#:

    Code:
    [DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string GetSerialHD();
    
    ...
    string GetHD = GetSerialHD();
    function GetSerialHD() always returns null, but the same code in a console application C++ for testing works well.

    thanks

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: DLL C++ and C#

    You need to declare the c-style function to take a string buffer and buffer size as parameters, not return a pointer to a string. For an example, see how GetComputerName is declared in the winapi, then look on pinvoke.net to see how it is called from .net.

    Btw, this code may 'work' in c, but it isn't the proper way to do it - a function should never return a variable to a local string.

  3. #3
    Join Date
    May 2020
    Posts
    3

    Re: DLL C++ and C#

    Quote Originally Posted by Arjay View Post
    You need to declare the c-style function to take a string buffer and buffer size as parameters, not return a pointer to a string. For an example, see how GetComputerName is declared in the winapi, then look on pinvoke.net to see how it is called from .net.

    Btw, this code may 'work' in c, but it isn't the proper way to do it - a function should never return a variable to a local string.

    but this test function works well

    Code:
    __declspec(dllexport) char* __stdcall Mytest()
        {
            char szSampleString[] = "Hello World";
            ULONG ulSize = strlen(szSampleString) + sizeof(char);
            char* pszReturn = NULL;
            pszReturn = (char*)::CoTaskMemAlloc(ulSize);
            strcpy(pszReturn, szSampleString);
            return pszReturn;
        }
    
    
         from c#
         string ret = Mytest();  //works well

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: DLL C++ and C#

    Works well? You mean by leaking memory?

    The caller of the dll needs to be responsible to allocate and clean up memory. The dll can't do it, because if it allocated the memory, it wouldn't know when to free it, so the STANDARD Windows practice is to allocate a buffer in the caller, and pass the buffer and its size to the dll.

    Look at any WinApi function that needs to return a string and they all do it by getting passed a buffer and a size.

    As I mentioned, see GetComputerName on how to properly declare such a function. https://docs.microsoft.com/en-us/win...tcomputernamew

  5. #5
    Join Date
    May 2020
    Posts
    3

    Re: DLL C++ and C#

    Quote Originally Posted by Arjay View Post
    Works well? You mean by leaking memory?

    The caller of the dll needs to be responsible to allocate and clean up memory. The dll can't do it, because if it allocated the memory, it wouldn't know when to free it, so the STANDARD Windows practice is to allocate a buffer in the caller, and pass the buffer and its size to the dll.

    Look at any WinApi function that needs to return a string and they all do it by getting passed a buffer and a size.

    As I mentioned, see GetComputerName on how to properly declare such a function. https://docs.microsoft.com/en-us/win...tcomputernamew


    I created a C # test project and called this function, and it returns me a string correctly

    unfortunately I am not an expert in C ++, I would just like to solve this problem

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: DLL C++ and C#

    Quote Originally Posted by HenryDev View Post
    I created a C # test project and called this function, and it returns me a string correctly
    Yes. But it produces the memory leaks! Your DLL allocates some piece of memory by every call. And it never deallocates these pieces!

    Quote Originally Posted by HenryDev View Post
    unfortunately I am not an expert in C ++, I would just like to solve this problem
    Then change the function in the DLL. It should have two parameters (the same as GetComputerName Arjay mentioned).
    It should NOT allocate any memory that it won't be able to free back.
    It will just copy something to the buffer passes as a (first) parameter and ensure that the buffer size is enough for the text it will copy.
    Victor Nijegorodov

  7. #7
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: DLL C++ and C#

    The c/c++ dll should look something like (not tested):

    Code:
    _declspec(dllexport) void __stdcall Mytest(char* buf, int buflen)
        {
            char szSampleString[] = "Hello World";
            strncpy_s(buf, buflen, szSampleString, _TRUNCATE);
        }
    with the caller allocating/deallocating the memory.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: DLL C++ and C#

    There are a couple of things to consider when pinvoking between C# and C. The first is C# strings are all UNICODE character set internally. The 2nd is what target is C# code getting compiled for - 32 or 64 bit?

    Since C# is UNICODE, it makes sense to expose strings in the C dll as UNICODE, i.e. not as char *. So the function prototype becomes:
    Code:
    declspec(dllexport) BOOL __stdcall GetSerialHD(LPWSTR lpBuffer, LPDWORD nSize );
    While the Windows convention would have you create two separate function exports, an A suffix MCBS variant GetSerialHDA and a W UNICIDE variant GetSerialHDW, that would be probably be overkill since only the UNICODE variant is needed.

    With regard to 32 or 64 bit.. you'll need to compile the C dll to match the target of what the C# assembly is compiled for, i.e. you can't call a 32 bit C dll from a 64 bit C# assembly and vice versa.

    All that aside, is the C dll even needed? I ask because if you are using the C dll to only make WMI calls, you can do that in C# (as C# has WMI classes to use directly).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured