Loading SDL window in C++ from C# application using CLR C++ wrapper does not work

StackOverflow https://stackoverflow.com/questions/23134491

  •  05-07-2023
  •  | 
  •  

سؤال

The goal of my application is to load a simple SDL window from a C# application via a C++ CLR wrapper. To do the job done I created 3 projects:

  • The one is the C++ library which load the SDL window (type = lib).
  • The second one is the wrapper written in C++ CLR (type = dll).
  • And the last one is of course the C# basic application (type = exe).

The C++ library:

INCLUDE:

#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();
}

Until here nothing special: just the basic initialization of an SDL window (just for information the code compiled as .exe application displays correctly the window).

Now the wrapper written in CLR C++:

INCLUDE:

#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();
}

As you can see, I've linked my C++ static library in my CLR project and I call all the methods (for information if I compile the CLR project as .exe application and the C++ project as .lib application, the SDL window displays correctly too).

And finally the C# main application:

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();*/
        }
    }
}

As you can see I just call the methods contained into my CLR wrapper (Here, for a sake of simplicity, I just call the 'Init' method). Nothing more. But after compilation I have the following exception:

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.

It seems not find the WrapperCLR.dll but it's not the case directly. Actually, if I erase in the 'TargetDisplay.cpp' file all the SDL syscalls, the program compiles, and the execution works.

But of course there is no display because the SDL syscalls are disabled. So the WrapperCLR.dll is found by the system. So I wonder if it does not found the SDL2.dll library.

Maybe it's not possible to load an SDL C++ program as static library from a C# application via a C++ CLR wrapper? Or maybe I have to add a specific information of linkage in the assembly file of directly in my source code.

هل كانت مفيدة؟

المحلول

I think it's just the issue with paths to the individual DLLs as you said.

IIRC in Visual Studio, projects are by default launched with current current directory set to $(ProjectDir) and executed from $(OutDir)\$(Configuration).

Make sure you have the WrapperCLR.dll and SDL2.dll in these directories for the top-level, C# project.

It works when you disable all calls to the DLL because then its imports are removed completely (optimization).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top