从C ++ \ CLI DLL调用C#DLL时代码崩溃了? [英] Code crashes while Calling C# dll from a C++\CLI dll?

查看:96
本文介绍了从C ++ \ CLI DLL调用C#DLL时代码崩溃了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢您的回复。



和抱歉如果我的Q?不够清楚。让我再试一次。



我真的不想先给出代码,因为我不想让你的回复偏向代码。我的第一个要求是,知道解决这个问题的最佳方法是什么。



我有一个C ++主机Exe项目和一个C#插件类型项目,我想要一个他们之间的沟通方式。所以我试着在它们之间添加一个C ++ \CLI层。



此外我不是EXE项目的所有者所以我不能做任何改变它。 C#项目更像是一个插件类型的项目。这里代码由EXE调用,而不是由C#调用,即EXE从特定txt文件中给出的路径加载C ++ dll,然后调用特定方法。而且我可以在C#项目中做一点改变,但不要像改变项目类型那样大。



所以用简单的话说,开始我的执行我必须从C#创建特定类的对象,但作为给定的流。 EXE开始调用功能。



如果你认为这是最好的方法,我可以提供代码,虽然我没有编写很多代码我想完成呼叫流程。



问题1)

所以如前所述,我首先尝试在中间只添加C ++ \CLI层,但它不起作用,我不知道为什么?作为主机exe正确调用C ++ DLL,我的C ++ DLL正确调用C ++ \ _CLI dll。但是当我从C ++中执行与C ++ \ CLI相同的功能时,主机exe无法调用它。



问题2)

此外我能够创建一个Manage对象在同一个项目中定义的类的C ++ \ _CLI里面但是当我尝试使用C#dll中定义的类时,我得到了以下异常。



我得到以下异常: -



消息=无法加载文件或程序集 MY_C_Sharp.dll,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null''或其中一个依赖项。系统找不到指定的文件。



C ++,C#dll和它的所有依赖项都在同一个文件夹中。

Thanks for reply.

and Sorry If my Q? was not clear enough. Let me try again.

I really didn''t wanted to give the code at first because I didn''t wanted to make your reply bias to the code. My first requirement is, to know what is the best approach to tackle this problem.

I have a C++ host Exe project and a C# plugin type project and I want a communication way in between them. So I tried to add a C++\CLI layer in between them.

Moreover I am not the owner of EXE project so I can''t make any change in it. C# project is more like a plugin type of project. Here the code is called by EXE not by C# i.e. EXE loads the C++ dll from the path given in a specific txt file and then calls a specific method. And I can make a little bit change in C# project but not a big one like change the project type.

So in simple words, to start my Execution I have to create an object of a specific class from C# but as the flow given. EXE starts the calling of functionality.

If you think this is the best approach, I can provide the code, though I haven''t written much of the code as I wanted to complete the calling flow.

Problem 1)
So as said before, I first tried to add only C++\CLI layer in between but it didn''t work, which I don''t know why? as host exe calling C++ dll properly, and my C++ dll calling the C++\CLI dll properly. but when I extern the same function from C++\CLI as done from C++, host exe is not able to call it.

Problem 2)
Moreover I am able to create a Manage object inside the C++\CLI for the class defined in the same project but when I tried same with the class defined in C# dll I am getting following exception.

I am getting following exception :-

Message = "Could not load file or assembly ''MY_C_Sharp.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'' or one of its dependencies. The system cannot find the file specified."

The C++ , C# dll and it all dependency are in the same folder.

推荐答案

CREO与C ++,C ++ / CLI和C#位于同一个文件夹中吗? EXE将在自己的路径或显式路径上搜索DLL,但如果第一个DLL加载了路径,我不认为后续的DLL会在该目录中找到。



所以,如果你有DirectoryA\App.Exe,DirectoryB \ _Cpp.DLL,DirectoryB \CppCli.DLL和DirectoryB \ _sharp.DLL,我认为如果DirectoryB是不在应用程序路径中,因为用于加载的当前目录是DirectoryA而不是directoryB。



C#DLL也依赖于除framwork之外的DLL本身?



首先要尝试的是将所有DLL移动到EXE目录。



另一种方法是指定(应用程序)路径,以便搜索额外的目录。



另一种可能是合并所有DLL。我从不尝试过。



在.NET中,如果你不想遵循通常的加载规则,你可以挂钩程序集加载。或者你可以显式加载程序集。



你有没有理由使用这么多的DLL?也许你应该有一个DLL(C ++ / CLI或C#)并且系统更简单。
Does the CREO is in the same folder as C++, C++/CLI and C#? The EXE will search DLLs on it own path or an explicit path but if the first DLL is loaded with a path, I don''t think that subsequent DLLs will be found in that directory.

So if you have DirectoryA\App.Exe, DirectoryB\Cpp.DLL, DirectoryB\CppCli.DLL and DirectoryB\Csharp.DLL, I think it won''t work if the DirectoryB is not in the application path as the current directory that is used for loading is DirectoryA and not directoryB.

Also does C# DLL has dependencies on DLLs other than those from the framwork itself?

The first thing to try would be to move all DLLs to the EXE directory.

An alternative might be to specify the (application) path so that extra directories would be searched.

Another possibility might be to merge all DLLs. I never try it.

In .NET you can hook assembly loading if you don''t want to follows usual loading rules. Or you can explicitly load an assembly.

Do you have any reason why you are using so many DLLs? Maybe you should have a single DLL (either C++/CLI or C#) and have a simpler system.


我不知道我是否能很好地解决问题,所以假设:

1)CREO是一个本机应用程序,可以利用本机DLL插件(即导出CREO将使用的已知函数的插件。

2)你想实现插件使用C#。



我认为你采用C ++ \ CLI方法是完全可以接受的。在这种情况下,您将导出所需的函数(由CREO调用的函数),作为本机C ++方法,然后在其中从这些方法调用托管条目。但是你应该仔细考虑:

1)C ++ \ CLI层应该服从CREO的位数(64或32)。

2)C#层可以是任何CPU或具有完全相同的位数。

3)C#dll应该位于CREO的相同目录中,或者在Assembly Cache中,或者您应该提供程序集定位器功能。如果其他任何问题都可以,我猜这就是问题的根源。
I don''t know if I got the problem well, so assuming that:
1 )CREO is a native application that can utilize native DLL plugins (i.e plugins that export know functions that will be used by CREO.
2 ) You want to implement the plug in using C#.

I think your approach of a C++\CLI approach is quite acceptable. In this case you would export the required functions (those that are called by CREO), as native C++ methods within which you then call the managed entries from these methods. But you should carefully consider:
1) The C++\CLI layer should obey the bitness(64 or 32) of CREO.
2) The C# layer can be "Any CPU" or with exact same bitness.
3) The C# dll should be in same directory of CREO, or in Assembly Cache, or you should provide an assembly locator functionality. This is what I guess is the root of your problem if anything else is OK.


// CodeProjectSample.h



如果我仍然是对的,你已经设法导出一个现在由主应用程序正确调用的条目



剩下的问题是你仍然需要手动将所有DLL复制到目标文件夹。

我相信如果你已经将C#层添加为对CLI代码的参考,当您编译代码时,

所需的DLLS(调试或发布)将被复制到CLI dll所在的同一文件夹。

现在您设置要加载的主应用程序你的DLL在所有其他dll所在的目标文件夹中,当你b $ b开始使用C#层中的代码时,实际上你正在命令CLR加载C#dll,这将失败,因为它不是

位于主app文件夹中。

可以使用AssemblyResolveHandler或添加AppDomain私有搜索路径的路径来解决。但是,在尝试调用C#层之前完成这些操作非常重要。因此,如果你在主函数中放入

C#调用方法,因为在执行此函数之前,CLR需要加载请求的DLL,你

没有机会做任何fixups。



以下代码为上述考虑的样本





// CodeProjectSample.h

If I''m still right, you have managed to export an entry that is now
correctly called by the main application.
The remaining problem is that you still need to manually copy all DLLs to the destination folder.
I believe that if you had added the C# layer as refrence to CLI code, when you complile the code,
the required DLLS (Debug or Release) will be copied to same folder where CLI dll is located.
Now you setup the main app to load your DLL in the destination folder where all other dlls are located, when you
start using the code in C# layer, in fact you are ordering CLR to load the C# dll which will fail, since it is not
located in the main app folder.
It could be solved using an AssemblyResolveHandler or adding path to private search path of AppDomain. But it is
very important that these actions be done before any attempt to call the C# layer. Therefore if you put the
C# call method in the main function, since before executing this function, CLR need to load the requested DLL, you
have no chance to do any fixups.

Following code is a sample for above consideration


*/

#pragma once


using namespace System;
using namespace System::Reflection;

namespace CodeProjectSample {

	public ref class Helper
	{
	public:
		// TODO: Add your methods for this class here.
		static int DoWork()
		{
			//CShrapDLL::MyClass^ inst = gcnew MyClass();
			//return inst->DoWork();
			return 0;
		}
		static String^ GetMyDllPath()
		{
			String^ myLocation = Helper::typeid->Assembly->Location;
			return System::IO::Path::GetDirectoryName(myLocation);

		}
		static Helper()
		{
			// Following line should resolve the problem by adding 
			// the current dll path to assembly search path.
			AppDomain::CurrentDomain->AppendPrivatePath(GetMyDllPath());
			// Even if above fails, adding an AssemblyResolveHandler will do that.
			AppDomain::CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(&CurrentDomain_AssemblyResolve);
		}
		static Assembly^ CurrentDomain_AssemblyResolve(System::Object^ sender,System::ResolveEventArgs^ args)
		{
			// You may manually load the assembly here by correcting the path
			String^ CorrectedPath = args->Name; // Change it to some correctin action.
			return Assembly::Load(CorrectedPath);
		}
	};
}



// This is the exorted entry. ''#pragma comment'' is only the way i like to export entries
// you may use whatever method you prefer.
// just note that the function doesnot directly call the C# code, so that
// CLR can start executing before it tries to load any additional (C#) layer dlls.
// The static constructor of the Helper class does initialize the necessary fix ups.
// After that we can now safely call DoWork, that will call the C# layer.

#pragma comment(linker,"/EXPORT:PluginEntry=_PluginEntry@0");
extern "C" int __stdcall PluginEntry()
{
	CodeProjectSample::Helper::DoWork();
	return 0;
}


这篇关于从C ++ \ CLI DLL调用C#DLL时代码崩溃了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆