简体   繁体   中英

Why can't i see some C++ DLL ( support CLR ) in C# project ?

I wrote simple C++ Dll ( win32 ) and i change the properties to be 'Common Language Runtime Support (/clr)' -

I created new Simple winform project ( C# 4.0 ) and i created reference to the C++ project ( the C++ DLL ).

Now i can't see the C++ dll in the C# project - i cant use it and i dont know why.

The types you created in your C++ dll are still native. You need to explicitly declare them as managed types. For example:

ref class SomeType { }

declares a managed class (note the ref keyword). It's not quite that easy though. Your native code won't get magically converted to managed code (a few basic data types like int are, but not things like std::string ). If you really want to take full advantage of C++/CLI for interop, you should take the time to learn about the syntax differences.

If you have, for example, this unmanaged function:

bool fooFunction(int firstParameter, int secondParameter);

If you want to make it visible to managed code you have to wrap (as first, simple, step) it into a managed class:

public ref class MyClass abstract sealed
{
public:
    static bool Foo(int firstParameter, int secondParameter)
    {
        return fooFunction(firstParameter, secondParameter);
    }
};

This is a simple exam, if you have to interop with complex type you may need to wrap them all. For example if you have to interop with a function that accepts a string you have to manage this. Usually I use a class like this:

ref class UnmanagedString sealed
{
public:
    UnmanagedString(String^ content) : _content(content)
    { 
        _unicodePtr = _ansiPtr = IntPtr::Zero; 
    }

    ~UnmanagedString()
    { 
        Free(); 
    }

    operator LPWSTR()
    { 
        if (_content == nullptr)
            return NULL;

        Free();

        _unicodePtr = Marshal::StringToHGlobalUni(_content);
        return reinterpret_cast<LPWSTR>(_unicodePtr.ToPointer());
    }

    operator LPCSTR()
    { 
        if (_content == nullptr)
            return NULL;

        Free();

        _ansiPtr = Marshal::StringToHGlobalAnsi(_content);
        return reinterpret_cast<LPCSTR>(_ansiPtr.ToPointer());
    }

    virtual System::String^ ToString() override
    {
        return _content;
    }

    virtual int GetHashCode() override
    {
        return _content->GetHashCode();
    }

    virtual bool Equals(Object^ obj) override
    {
        return _content->Equals(obj);
    }

private:
    IntPtr _unicodePtr, _ansiPtr;
    String^ _content;

    void Free()
    {
        if (_unicodePtr != IntPtr::Zero)
        {
            Marshal::FreeHGlobal(_unicodePtr);
            _unicodePtr = IntPtr::Zero;
        }

        if (_ansiPtr != ntPtr::Zero)
        {
            Marshal::FreeHGlobal(_ansiPtr);
            _ansiPtr = IntPtr::Zero;
        }
    }
};

Using this class you can call a function like void foo(LPCSTR pszText) with foo(UnamangedString(myManagedString)) . More complex are the calls you have to do and more code you have to write to interop between them.

Note: simply exposing a 1:1 managed interface to unmanaged functions will make your C# code harder to read, I suggest you write a true OO interface to hide underlying implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM