找不到EntryPoint

时间:2014-10-23 09:10:37

标签: c# c++ pinvoke

我正在尝试使用Platform Invoke从C#执行C ++ DLL中的一些函数。我收到了一个未找到EntryPoint的错误,我无法弄清楚原因。希望有人可以帮助我。 :)

C ++声明:

Declaration

C#PInvoke代码:

PInvoke

Dumpbin和错误:

Dump enter image description here

编辑:使用EntryPoint="?CreateClass@Drive@UnmanagedDLL@@QAEPAV12@XZ"有效,但我不应该引用CreateClass吗?

1 个答案:

答案 0 :(得分:4)

此代码块:

extern "C" UNMANAGEDLL_API Drive* Drive::CreateClass()
{
    return new Drive();
}

您是否尝试使用C链接导出类方法?我想知道为什么它甚至编译。使用C链接导出的函数不应该是类方法:

Drive* Drive::CreateClass()
{
    return new Drive();
}

extern "C" UNMANAGEDLL_API Drive* CreateClass()
{
    return Drive::CreateClass();
}

这是因为C链接不能应用于类方法(它需要thiscall并命名为mangling)。你可以DllImport类方法吗?首先忘记使用C链接然后删除extern "C"。现在,您必须使用DllImport参数EntryPoint 原始方法名称,但您还必须更改调用约定(因为默认值为StdCall,但类使用{{1} }}),如果你忘记,那么只需要你运行炸弹。一个例子(仅供参考,如果您可以访问类API并且可以添加 plain C导出函数,我会非常避免这种):

ThisCall

像这样使用:

[DllImport("SomeDll.dll",
    EntryPoint="?CreateClass@Drive@UnmanagedDLL@@QAEPAV12@XZ",
    CallingConvention = CallingConvention.ThisCall)]
public static extern IntPtr CreateClass(IntPtr thisPointer);

现在你可以使用IntPtr drive = CreateClass(IntPtr.Zero); 来调用其他方法(你有正确的调用约定,在X86上,这是通过drive传递的,而不是像在{ECX那样传递。 1}},在X64上,这是一个完全不同的故事,但使用属性,它将同时适用于两者。)

修改

如何使用C ++ / CLI完成?它应该更容易和无痛(实现只是一个骨架)。

部首:

StdCall

实现:

public ref class Drive sealed
{
public:
    ~Drive();

    // Assuming you want to keep a static factory method
    static Drive^ CreateClass();

    property bool State
    {
        bool get();
        void set(bool value);
    }

private:
    Drive();

    DriveNativeImpl* _drive;
};

在C#中,您会看到普通托管类:

Drive::Drive()
{
    _drive = new DriveNativeImpl();
}

Drive::~Drive()
{
    delete _drive;
}

Drive^ Drive::CreateClass()
{
    return gcnew Drive();
}

bool Drive::State::get()
{
    assert(_drive != null);

    return _drive->GetState();
}

void Drive::State::set(bool value)
{
    assert(_drive != null);

    _drive->SetState(value);
}