【问题标题】:Loading SDL window in C++ from C# application using CLR C++ wrapper does not work使用 CLR C++ 包装器从 C# 应用程序加载 C++ 中的 SDL 窗口不起作用
【发布时间】:2014-04-17 13:29:21
【问题描述】:

我的应用程序的目标是通过 C++ CLR 包装器从 C# 应用程序加载一个简单的 SDL 窗口。为了完成这项工作,我创建了 3 个项目:

  • 一个是加载 SDL 窗口的 C++ 库 (type = lib)。
  • 第二个是用 C++ CLR (type = dll) 编写的包装器。
  • 最后一个当然是C#基础应用(type = exe)。

C++ 库:

包括:

#ifndef __TARGET_DISPLAY_HPP__
# define __TARGET_DISPLAY_HPP__

#include <SDL/SDL.h>

class TargetDisplay
{
    public:
        TargetDisplay(void);
        ~TargetDisplay(void);

    public:
        void Init(void);
        void Update(void);
        void Render(void);
        void Quit(void);
        bool IsAlive(void);

    private:
        SDL_Window *fenetre;
        SDL_GLContext contexteOpenGL;
        SDL_Event evenements;
        bool terminer;
};

#endif // !__TARGET_DISPLAY_HPP__

SRC:

#include "TargetDisplay.hpp"

//Initialization

TargetDisplay::TargetDisplay(void)
    :   terminer(false)
{

}

//Destruction

TargetDisplay::~TargetDisplay(void)
{

}

//Others

void TargetDisplay::Init(void)
{
    SDL_Init(SDL_INIT_VIDEO);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    fenetre = SDL_CreateWindow("Test SDL 2.0", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, 320, 240, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);

    contexteOpenGL = SDL_GL_CreateContext(fenetre);
}

void TargetDisplay::Update(void)
{
    SDL_WaitEvent(&evenements);

    if(evenements.window.event == SDL_WINDOWEVENT_CLOSE)
        terminer = true;
}

void TargetDisplay::Render(void)
{

}

bool TargetDisplay::IsAlive(void)
{
    return (true);
}

void TargetDisplay::Quit(void)
{
    SDL_GL_DeleteContext(contexteOpenGL);
    SDL_DestroyWindow(fenetre);
    SDL_Quit();
}

直到这里没有什么特别的:只是 SDL 窗口的基本初始化(仅作为信息,编译为 .exe 应用程序的代码正确显示窗口)。

现在是用 CLR C++ 编写的包装器:

包括:

#ifndef __WRAPPER_DISPLAY_HPP__
# define __WRAPPER_DISPLAY_HPP__

#include <iostream>
#include "../TargetCPP/TargetDisplay.hpp"

namespace Test
{
    public ref class WrapperDisplay
    {
        public:
            WrapperDisplay(void);
            ~WrapperDisplay(void);

        public:
            void Init(void);
            void Update(void);
            void Render(void);
            bool IsAlive(void);
            void Quit(void);

        private:
            TargetDisplay *m_pTarget;
    };
}

#endif // !__WRAPPER_DISPLAY_HPP__

SRC:

#include "WrapperDisplay.hpp"

//Initialization

Test::WrapperDisplay::WrapperDisplay(void)
{
    this->m_pTarget = new TargetDisplay();
}

//Destruction

Test::WrapperDisplay::~WrapperDisplay(void)
{

}

//Others

void Test::WrapperDisplay::Init(void)
{
    this->m_pTarget->Init();
}

void Test::WrapperDisplay::Update(void)
{
    this->m_pTarget->Update();
}

void Test::WrapperDisplay::Render(void)
{
    this->m_pTarget->Render();
}

bool Test::WrapperDisplay::IsAlive(void)
{
    return (this->m_pTarget->IsAlive());
}

void Test::WrapperDisplay::Quit(void)
{
    this->m_pTarget->Quit();
}

如您所见,我已在我的 CLR 项目中链接了我的 C++ 静态库并调用了所有方法(有关信息,如果我将 CLR 项目编译为 .exe 应用程序并将 C++ 项目编译为 .lib 应用程序,则 SDL窗口也能正确显示)。

最后是 C# 主应用程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WrapperTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Test.WrapperDisplay wrapper = new Test.WrapperDisplay();

            wrapper.Init();
            /*wrapper.Update();
            wrapper.Render();
            wrapper.Quit();*/
        }
    }
}

如您所见,我只是调用了包含在 CLR 包装器中的方法(这里,为了简单起见,我只调用了“Init”方法)。而已。但是编译后我有以下异常:

An unhandled exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll

Additional information: Could not load file or assembly 'WrapperCLR.dll' or one of its dependencies. The specified module could not be found.

似乎找不到WrapperCLR.dll,但事实并非如此。实际上,如果我在“TargetDisplay.cpp”文件中删除所有 SDL 系统调用,程序就会编译,并且执行正常。

当然没有显示,因为 SDL 系统调用被禁用。所以WrapperCLR.dll被系统找到了。所以我想知道它是否没有找到SDL2.dll库。

也许无法通过 C++ CLR 包装器从 C# 应用程序将 SDL C++ 程序作为静态库加载?或者也许我必须直接在我的源代码中的程序集文件中添加链接的特定信息。

【问题讨论】:

  • 你为什么要这样做?这是非常罕见的
  • FileNotFoundException 具有误导性,直到您查看详细描述“无法加载文件或程序集 WrapperCLR.dll 或其依赖项之一

标签: c# c++ sdl wrapper


【解决方案1】:

我认为这只是您所说的各个 DLL 路径的问题。

Visual Studio 中的 IIRC,项目默认启动时当前目录设置为 $(ProjectDir) 并从 $(OutDir)\$(Configuration) 执行。

确保顶级 C# 项目的这些目录中有 WrapperCLR.dllSDL2.dll

当您禁用对 DLL 的所有调用时它会起作用,因为它的导入将被完全删除(优化)。

【讨论】:

  • 非常感谢。实际上,SDL2.dll 库没有复制到正确的目录中。再见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
  • 2019-01-25
相关资源
最近更新 更多