Create and use DLL libraries written in C++ on . NET C#

Asked

Viewed 56 times

-2

Because of the fact. NET is reversible, I need to encode part of my program in C++, but I still need Windows Forms, so I thought I’d create Dlls written in C++ to perform some key tasks (like license verification) and keep the rest of the code in C#. These Dlls will need to receive and return various data, but mostly strings. I performed some tests with integer values, and others with strings. I’m not getting build errors (not from the DLL, nor from the program using it) but when running I get the errors:

System.Dllnotfoundexception when I work with strings; and System.Entrypointnotfoundexception when I use whole;

The compiled DLL files I am placing in the directory I inform when importing it, and I know that it is being located as the errors are different when I don’t put them there.

I am compiling the projects with Visual studio, and below are the codes used:

Crypto. h (DLL header) - C++

/// crypto.h
#ifdef CRYPTO_EXPORTS
#define CRYPTO_API __declspec(dllexport)
#else
#define CRYPTO_API __declspec(dllimport)
#endif

#include <string>

CRYPTO_API std::string crypto_RIPEMD160(std::string);

Crypto.cpp (DLL Functions) - C++

// crypto.cpp : Define as funções exportadas para a DLL.

#include "pch.h"
#include "framework.h"
#include "crypto.h"

#include <string>
#include <openssl/ripemd.h>

//Constantes
#define AES_BLOCK_SIZE 16
CRYPTO_API std::string crypto_RIPEMD160(std::string str)
{
    int tam_str = str.length();
    std::string hash;
    unsigned char* msg = (unsigned char*)malloc(sizeof(unsigned char) * tam_str);
    unsigned char* resp = (unsigned char*)malloc(sizeof(unsigned char) * AES_BLOCK_SIZE);
    //transcrever dados da string para o char
    for (int i = 0; i < tam_str; i++) {
        msg[i] = str[i];
    }
    #pragma warning(suppress : 4996)
    resp = RIPEMD160(msg, tam_str, NULL);
    for (int i = 0; i < AES_BLOCK_SIZE; i++) {
        hash[i] = resp[i];
    }
    return hash;
}

Target project (where the library will be used) - C#

using System.Runtime.InteropServices;
namespace exemplo
{
    public class Win32
    {
        [DllImport(@"..\dlls\crypto.dll", CallingConvention = CallingConvention.Cdecl)] public static extern string crypto_RIPEMD160(string str);
    }
    public class MinhaClasse
    {
        public void teste()
        {
            string teste = Win32.crypto_RIPEMD160("TESTE");
        }
    }
}

I’m a beginner in programming, and I haven’t really found any topic that could help me so far with this problem. If anyone can help me, I’d appreciate it!

Note: The codes do not necessarily return the correct hashes, I am worried about the data exchanges between the functions.

Grateful from now on!

  • 1

    Well, any language can be reverse-engineered, up to c++. To use a DLL from another language within . net just create a DLL or a COM if it is a DLL just put in a nuget package for example, or simply reference it in the project.

1 answer

0

Here is an example of how to pass a string from C# to C++ and vice versa.

// CDll.dll (C++ Dll)
// CDll.h
#pragma once
#include <iostream>
#include <Windows.h>

#ifdef CDLL_EXPORTS
#define CDLL_API extern "C" __declspec(dllexport)
#else
#define CDLL_API __declspec(dllimport)
#endif

CDLL_API int receiveString(const char* str)
{
    char chr[255];
    strcpy_s(chr, str);
    std::cout << "[C++] received string: " << chr << std::endl;
    return 0;
}

CDLL_API int sendString(char* chr)
{
    const char* str = "Hello from C++";
    strcpy_s(chr, strlen(str) + 1, str);
    return 0;
}
// CGui.exe (C# WinForms)
// Form1.cs
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace CGui
{
    public partial class Form1 : Form
    {
        [DllImport(@"CDll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "receiveString")]
        static extern int sendStringToCDll(string str);

        [DllImport(@"CDll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "sendString")]
        static extern int receiveStringFromCDll(StringBuilder str);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string sendString = "Hello from C#";
            sendStringToCDll(sendString);

            StringBuilder receiveString = new StringBuilder();
            receiveStringFromCDll(receiveString);
            Console.WriteLine("[C#] " + "received string: " + receiveString.ToString());
        }
    }
}
  • Thank you very much for your reply! But I still get the error below: System.Runtime.Interopservices.Marshaldirectiveexception Hresult=0x80131535 Message=Unable to perform marshaling of 'Return value': Invalid combination of managed/unmanaged type (Int32/Uint32 must be combined with I4, U4 or Error).

  • Put as your code to take a look.

  • I will post as "answer" because I can not put here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.