【问题标题】:P/Invoke. How to call unmanaged method with marshalling from C#?P/调用。如何通过 C# 编组调用非托管方法?
【发布时间】:2012-02-09 12:48:57
【问题描述】:

我在使用 P/Invoke 时遇到了问题。我从 c# 代码调用 .dll(在 c++ 上实现)。有一个类,其中包含下一个方法:

virtual AudioFileList *API  CreateAudioFileList ()=0;
virtual bool API  DisposeAudioFileList (AudioFileList *iAudioFileList)=0;

AudioFileList 类看起来像:

virtual bool API  GetFile (long index, std::string *oPath, AudioFileInfo *fileInfo)=0;
virtual long API  GetNumberFiles ()=0; 

所以,问题是我如何调用 CreateAudioFileList 方法并将结果传递给 DisposeAudioFileList 来自 C# 代码? 谢谢!

【问题讨论】:

    标签: c# interop pinvoke marshalling intptr


    【解决方案1】:

    我一直使用它来生成我的静态外部密钥

    http://clrinterop.codeplex.com/releases/view/14120

    【讨论】:

    • 有自动化工具吗?很棒的发现!
    【解决方案2】:

    不幸的是,没有简单的方法可以通过 P/Invoke 调用本机 C++ DLL 模块中的类。然而,有一个 solution 的 Visual C++ 团队博客帖子,但它很复杂。

    还有一个您可能会觉得有用的链接:http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/5df04db1-bbc8-4389-b752-802bc84148fe/

    【讨论】:

      【解决方案3】:

      CodeProject 上的这篇文章解释了如何处理这种编组。

      How to Marshal a C++ Class

      【讨论】:

        【解决方案4】:

        您不能,因为名称错误。您应该投资学习 C++/CLI。这将允许您创建一个中间层,该层提供适当的编组,并且不受 C++ 中名称修改的限制。

        这是它在 C++/CLI 中的样子(当然未经测试):

        .h

        public ref class ManagedAudioFileList
        {
        private:
            const AudioFileList* Native;
            // Replace AudioFileListManager with the class containing
            // the CreateAudioFileList and DisposeAudioFileList methods.
            const AudioFileListManager* Manager;
        
        public:
            ManagedAudioFileList(void);
            !ManagedAudioFileList(void);
            ~ManagedAudioFileList(void);
            // Insert various methods exposed by AudioFileList here.
        };
        

        .cpp

        ManagedAudioFileList::ManagedAudioFileList(void)
        {
            // Replace AudioFileListManager with the class containing the
            // CreateAudioFileList and DisposeAudioFileList methods.
            Manager = new AudioFileListManager();
            Native = Manager->CreateAudioFileList();
        }
        
        ~ManagedAudioFileList::ManagedAudioFileList()
        {
            Manager->DisposeAudioFileList(Native);
            delete Manager;
        }
        
        !ManagedAudioFileList::ManagedAudioFileList()
        {
        }
        
        // Wrap various methods exposed by AudioFileList.
        

        【讨论】:

        • 只是想让你知道这两个函数是纯虚函数,不会在 C++ DLL 中导出。你的“你不能,由于名字修改”的原因是不正确的。
        • @dave 你说对了一部分。原因比名称修改复杂得多,但“为什么”并没有真正有助于答案,所以我没有费心解释。如果直接调用,虚拟方法——不仅仅是纯虚拟方法——将无法按预期运行。纯虚方法根本不存在于它们的抽象类中,至少在传统的可调用意义上是这样。话虽如此,它们的具体实现仍然有地址,从技术上讲仍然可以导出,并且理论上可以通过 P/Invoke 相当骇人地调用。那时,名称修改可以忽略不计。
        • 非常好的观点。您知道您可以通过 P/Invoke 从 C# 调用 C++ 类方法,包括虚拟方法。
        • @dave 这在理论上是可行的,但是很老套,依赖于编译器,通常是个坏主意。
        • 它是一个 C++ dll。任何 C++ DLL 都依赖于编译器。你的 C++/CLI 方案其实就是基于这个思路。
        猜你喜欢
        • 2013-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 2010-12-25
        • 1970-01-01
        • 2013-09-30
        • 1970-01-01
        相关资源
        最近更新 更多