如果我的术语有点偏离,请原谅我.我对托管C++/CLI的了解非常有限.
我有一个MFC应用程序使用启用了/ clr选项的DLL.这个dll使用几个C#dll与使用WCF的服务器通信.在大多数情况下,这工作正常.
在C#的DLL中的一个,我已经添加扩展方法的System.Net.IPAddress类,将检索的对象的IPAddress子网掩码(使用UnicastIPAddressInformation类及其IPv4Mask).扩展方法在C#方面运行良好,但我无法弄清楚如何在托管C++/CLI代码中使用它.
首先,这甚至可能吗?如果是这样,托管C++/CLI端的语法是什么样的?我必须使用/ clr:pure选项才能使用吗?
以下是扩展方法的示例:
using System.Net;
using System.Net.NetworkInformation;
public static class IPAddressExtensions
{
public static IPAddress GetSubnetMask(this IPAddress address)
{
UnicastIPAddressInformation addressInfo = address.GetAddressInformation(); // elided
return ((addressInfo != null) ? addressInfo.IPv4Mask : null);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的托管C++代码中,如果可能的话,我将如何使用此扩展方法?
unsigned long bytes= 0x010000FF; // example address - 127.0.0.1
IPAddress^ address = gcnew IPAddress(BitConverter::GetBytes(bytes));
IPAddress^ subnet = address->GetSubnetMask(); // how do I do this???
Run Code Online (Sandbox Code Playgroud) 我有一个用托管代码(C++/CLI)编写的COM对象.我在标准C++中使用该对象.
当COM对象被释放时,如何强制立即调用COM对象的析构函数?如果那是不可能的,请调用我有Release()调用我的COM对象上的MyDispose()方法?
我的代码声明对象(C++/CLI):
[Guid("57ED5388-blahblah")]
[InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
[ComVisible(true)]
public interface class IFoo
{
void Doit();
};
[Guid("417E5293-blahblah")]
[ClassInterface(ClassInterfaceType::None)]
[ComVisible(true)]
public ref class Foo : IFoo
{
public:
void MyDispose();
~Foo() {MyDispose();} // This is never called
!Foo() {MyDispose();} // This is called by the garbage collector.
virtual ULONG Release() {MyDispose();} // This is never called
virtual void Doit();
};
我使用该对象的代码(本机C++):
#import "..\\Debug\\Foo.tlb" ... Bar::IFoo setup(__uuidof(Bar::Foo)); // This object comes from the .tlb. setup.Doit(); setup->Release(); // explicit release, not really necessary since …
我有VS2008解决方案包含一个项目,该项目生成一个C#可执行文件,该项目引用了一个生成包含C++/CLI和非托管C++的DLL的项目.
我想将这些合并到一个可执行文件中,因为C++ DLL包含我想要嵌入主可执行文件的安全代码.
我不能使用ILMerge,因为dll包含托管代码和非托管代码.建议的解决方案似乎是使用link.exe将C#程序集与C++目标文件链接起来.这就是我想要做的.
我手动编辑了c#可执行文件的项目文件以生成netmodule.我在可执行项目中添加了一个构建后步骤,以运行link.exe将c#netmodule和已编译的C++目标文件链接在一起,然后运行mt.exe来合并两个项目创建的程序集清单.这运行成功,但是exe仍然包含对C++项目的正常构建过程生成的dll中定义的c ++类型的引用和使用.
然后我在C++ dll的项目设置中指定了/ NOASSEMBLY,因此它还生成了一个netmodule.在C#项目中,我删除了对C++项目的引用,但在解决方案中添加了项目依赖性.我手动编辑了C#项目文件,包括类似于:
<ItemGroup>
<AddModules Include="..\Debug\librarycode.netmodule" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
即引用现在由C++项目生成的C++ netmodule.
但是,现在我的post build事件中的链接器步骤失败了:
error LNK2027: unresolved module reference 'librarycode.netmodule'
fatal error LNK1311: 1 unresolved module references:
Run Code Online (Sandbox Code Playgroud)
这完全可以理解,因为我没有链接到librarycode netmodule; 我链接在用于生成netmodule的C++目标文件中.
简而言之,如何将ac#executable和C++目标文件合并到一个程序集中?我错过了什么?
到目前为止我的引用源(来自MSDN上的link.exe命令链接引用等)是以下两篇文章:
非常感谢你提前.
我在Steve Teixeira的博客中完全遵循了这个例子,并证实它有效.使用反射器,我可以看到生成的可执行文件包含两个netmodule.c#netmodule包含对另一个netmodule的引用但没有名称?!如果将程序集移动到新目录,则第二个netmodule变为未引用(显然),但可执行文件仍然运行,因为c#netmodule中存在具有正确定义的类型.
请注意,原始c#netmodule确实包含对c ++ netmodule的命名引用,因此它必须是删除名称的链接器步骤.
试图在我的示例项目中遵循此示例,我已将/ ASSEMBLYMODULE参数添加到我的后期构建链接器步骤中.链接器现在失败了
LNK2022: metadata operation failed (80040427) : Public type 'MixedLanguageLibrary.Class1' is defined in multiple places in this assembly: 'MixedLanguageDemo.exe' and 'mixedlanguagelibrary.netmodule'
LINK : fatal error LNK1255: link failed because of metadata errors
Run Code Online (Sandbox Code Playgroud)
我猜这是链接器魔术删除我缺少的模块引用名称. …
如果我有任何类型的文件路径(.doc,.pdf,.png ...等),我想打开该文件,因为它是通过双击打开(无需确定主机程序).我的意思是:.doc文件需要通过MS Word或机器中存在的任何文字处理器打开,并设置为defualt文字处理器.
我们最近将一个Winforms项目从Visual Studio 2008迁移到了Visual Studio 2012.转换过程非常顺利,所有内容都很好,但我们现在正在努力与winforms设计器一起运行,它的运行速度非常慢.
举个例子,如果我们打开一个小表单(表单包含两个文本框,一个数字更新和两个按钮 - 所有标准内置控件,没有第三方),2012年大约需要40-45秒在2008年,它会在1或2秒内打开.对于我们较大的形式,这种差异更加明显.在2008年,打开表格需要大约7秒钟,但在2012年需要6分钟.最糟糕的是,这是一个阻塞动作,VS2012在打开表单时几乎完全没有响应.这也是通过单击表单的.h来实现的,所以我们不能仅仅通过坚持代码本身来轻松避免它.
还有其他人经历过这个吗?有谁知道它为什么会发生,如果有什么可以做的吗?
其他信息:我们的应用程序是一个C++/CLI winforms应用程序.在我们所有运行Windows 7 x64的开发机器上都可以看到这种行为.我的机器是Core i7 860 CPU,内存为12Gb(现在我正在对以上内容进行基准测试时超过60%) - 绰绰有余,我想.在任何情况下,我的系统运行速度都不慢,它只是VS2012的设计者.
编辑:只是为了进一步澄清,我们没有安装任何插件或类似的东西.这是一个处女VS2012安装.
EDIT2:它似乎也不是网络的东西.
.net c++-cli windows-forms-designer winforms visual-studio-2012
我的C#应用程序使用包装的C++代码进行计算.
C++标题:
__declspec(dllexport) void SetVolume(BYTE* data, unsigned int width);
Run Code Online (Sandbox Code Playgroud)
C++/CLI包装器:
void SetVolume(array<Byte>^ data, UInt32 width)
{
cli::pin_ptr<BYTE> pdata = &data[0];
pal->SetVolume(pdata, width);
}
Run Code Online (Sandbox Code Playgroud)
C# :
public startCalc()
{
byte[] voxelArr = File.ReadAllBytes("Filtered.rec");
palw.SetVolume(voxelArr, 490);
//GC.KeepAlive(voxelArr); makes no sense
}
Run Code Online (Sandbox Code Playgroud)
C++ SetVolume函数启动异步计算.voxelArr不再从受管方引用,并且是垃圾回收.
在非托管代码完成它的工作而不声明voxelArr为全局变量之前,如何防止此引用的垃圾收集?创建数组副本不是一个选项,因为实际上有很多数据.内部的积极等待startCalc()也不好.
我最近听说.dd一旦加载就可以运行代码,例如,当加载引用.dll的应用程序时.事件虽然我做了一些我自己的测试,并尝试在这里寻找答案,在谷歌我无法找到一些方法来生成.dll的初始化方法.
我想知道是否真的可以在应用程序加载时从.dll运行代码.
如果是这样,我该怎么办?
如果我编译并运行以下代码:
using namespace System;
ref class C1
{
public:
C1()
{
Console::WriteLine(L"Creating C1");
}
protected:
~C1()
{
Console::WriteLine(L"Destroying C1");
}
};
int main(array<System::String ^> ^args)
{
C1^ c1 = gcnew C1();
delete c1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...代码编译没有错误,并运行给我这个:
Creating C1
Destroying C1
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)
如果我在C++中执行相同操作,则会出现以下错误:
1>ProtectedDestructor.cpp(45): error C2248: 'C1::~C1' : cannot access protected member declared in class 'C1'
1> ProtectedDestructor.cpp(35) : compiler has generated 'C1::~C1' here
1> ProtectedDestructor.cpp(23) : see declaration of 'C1'
Run Code Online (Sandbox Code Playgroud)
...那么为什么它在CLI中有效?
我使用Cmake和visual studio构建了OpenCV二进制文件(.dll),它生成了.pdb文件,帮助我在代码中找到问题(部分!)
这次崩溃是如何造成的..
我正在使用一种软件,我们可以为任何特定程序设置互联网下载速度限制(传输速率).
现在,如果我将IP摄像头连接到下面的代码,我注意到我的应用程序需要大约100Kb/s的互联网使用率(传输速率) - 只有这样我才能无缝地观看直播.让我说我减少(设置)我的应用程序互联网使用量为10Kb/s [这是崩溃背后的原因] 在这种情况下,我应该能够在4秒内看到一个新的框架.
我收到访问冲突错误可能是因为(cap>>img;)上限试图到达ram中的位置并获取帧但是没有帧YET因为它仍然因为低网速而被下载.
很明显,指针到达ram中的某个位置以抓住尚未存在的帧.
一些有趣的行为...
Void OpenCamera()
{
VideoCapture cap("http://192.168.1.3:8080/video?x.xmjpeg");
Mat img;
while(true)
{
try
{
if(cap.isOpened()) //also tried grab + retrieve, crashes at grab
cap>>img; //code crashes here
}
catch(...)
{
cout<<"Camera Disconnected"<<endl;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我在同一个类中使用整个代码(在相同的头文件中),根本没有问题(新帧在4秒以上显示而不会使程序崩溃)但是如果我将代码放入一个单独的类(不同的头文件) ),然后调用该函数从类对象打开相机,然后如果减少 互联网速度它崩溃.
奇怪的行为 - 如果我一步一步调试,它永远不会崩溃!
当我使用ffmpeg构建opencv库时,我只获取opencv(opencv_world310.pdb)的.pdb文件 - 所以没有问题调试使用调用堆栈,但我没有得到fdb for ffmpeg(因为Opencv_ffmpeg.dll是预编译的,这是它崩溃的地方)
因此很难调试,构建ffmpeg不会产生pdb文件,因为它使用MSYS构建,
所以可以用我们的调试吗?
我包括来自visual studio调试的快照,一些有助于理解的变量:
typedef int (*CvGrabFrame_Plugin)( void* capture_handle ); [cap_ffmpeg_api.cpp]
protected: void* ffmpegCapture; [cap_ffmpeg.cpp]
static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = …Run Code Online (Sandbox Code Playgroud)