【发布时间】:2019-07-03 13:40:41
【问题描述】:
TL;DR
我有旧的 c++ 代码,它会做一些事情(有时会返回一些东西),调用其他 cpp 代码,但不是完整的类/obj。我无法更改此代码。我正在制作新的 c# 代码,我希望从中调用 c++ 代码。我不明白是创建一个调用原始遗留 c++ 的 dll,还是创建一个 CLR?这也称为旧版 cpp。下面我有我已经实现的示例代码(有问题)。
主要
我有无法更改的 legacy.cpp 和 legacy.h。
这不是类/对象,只有公共函数、值和#defines。 legacy.cpp 和 .h 都 #include 其他文件和 cpp 库来完成它的工作。
我有一个新项目,我可以在其中添加 C#、C++ 代码
我无法理解我需要做什么/研究才能从我的新 C# 代码中调用 legacy.cpp 中定义的任何函数(或值/定义)。
我看过的一些内容包括
-
托管 CLR 包装器
- DLLs??
CLR
我目前尝试创建一个 CLR(我觉得这不是我在这种情况下需要的),但是我在 clr_wrapper.cpp 中遇到了问题,它找不到对 foo() 的引用
//Wrapper.cpp
#include "Wrapper.h"
#include "abs\path\to\legacy\code\legacy.h"
#include "abs\path\to\legacy\code\legacy.cpp"
int foo_Wrapper()
{
return foo(); //int foo() is declared in legacy.h and defined in legacy.cpp
}
#pragma once
#include "abs\path\to\legacy\code\legacy.h"
#include "abs\path\to\legacy\code\legacy.cpp"
using namespace System; //What things use this?
//Can I just prepend System:: to whatever needs it?
namespace Wrapper {
public ref class Wrapper
{
public:
int foo_Wrapper();
};
}
foo_Wrapper() 无法调用 foo()。
我对这种方法的困惑是,我似乎需要将 clr 包装器制作成一个对象类,其中包含将根据需要调用的成员函数。导致obj.foo() 的语法。如果我选择做某种 CLR 包装器,这是需要做的吗?
DLL
我还考虑过将这一切都变成一个 dll,例如 (How to call C++ DLL in C#)
但是我对设置这个感到困惑。我目前的想法是让一个cpp dll调用原始cpp(即创建legacyDll.dll,它将调用foo(),然后我的主c#将调用extern“C”中定义的__declspec(dllexport)函数{}
当前设置(来自“如何在 c sharp 中调用 c dll”) dllmain.cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <iostream>
#include <Windows.h>
using namespace std;
extern "C"
{
__declspec(dllexport) void bar_Dll()
{
cout << "calling bar() in legacy code" << endl;
}
__declspec(dllexport) int foo_Dll()
{
cout << "calling foo() in legacy code" << endl;
//realistically I would have,
//return foo()
}
}
Class1.cs
using System;
using System.Runtime.InteropServices;
namespace Test_DLL_Calling
{
class Class1
{
[DllImport("dllmain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void bar_Dll();
[DllImport("dllmain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int foo_Dll();
public static void Main(string[] arg)
{
bar_Dll(); //The specified module could not be found (Exception)
Console.WriteLine(foo_Dll()); //Im guessing this will also ^^
}
}
}
这部分我不关注。属性是什么以及为什么以它们的方式完成?
【问题讨论】:
-
"属性是什么以及为什么要按照它们的方式完成?" 这就是文档的用途。对此类问题的回答应该是查找这些属性的文档以了解它们的作用或指示。 Microsoft 提供了一个方便的.NET API browser,它使查找任何类/类型(当然包括属性类型)及其想要了解的成员变得非常简单。 (或者,在 Visual Studio 中,将文本插入符号/光标移动到您想了解更多信息的属性上,然后按 F1 键)
-
一个 dll 有多个入口点。每个入口点都是 dll 中的一个公共函数。所以 dll 有两个方法 bar_Dll 和 foo_Dll 并且每个都返回一个整数。
-
制作一个新的 c++/CLI .DLL(c++/CLI dll 是原生 和 托管代码的混合体)"P" 这将在现有的 c/c++ .DLL "E" 周围充当一个简单的代理/外观模式。您的 C# 代码调用 "P" 中的类型并且不查看/关心 "E"。 "P" 将调用路由到 "E" 并将结果(如果有)作为托管类型返回。 无需处理繁琐的 dllexport 和/或 p-invoke。顺便说一句,根据您的需要,如果您不想,您不一定需要将所有 c++ 方法公开给 .NET。保持包装简单