我的应用程序的目标是通过C ++ CLR包装器从C#应用程序加载一个简单的SDL窗口。为了完成工作,我创建了3个项目:
type = lib
)的C ++库。type = dll
)编写的包装器。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 ++程序作为静态库?或者我可能需要在源代码中直接在汇编文件中添加链接的特定信息。
我认为这只是你所说的单个DLL路径的问题。
在Visual Studio中的IIRC,默认情况下启动项目,当前当前目录设置为$(ProjectDir)
并从$(OutDir)\$(Configuration)
执行。
确保在这些目录中为顶级C#项目安装了WrapperCLR.dll和SDL2.dll。
它禁用对DLL的所有调用,因为它完全删除了导入(优化)。