背景:作为更大任务的一部分,我需要使C#库可以被非托管C++和C代码访问.为了自己回答这个问题,过去几天/几周我一直在学习C++/CLI.
似乎有许多不同的方法来实现使用来自非托管C++和C的C#dll.一些简单的答案似乎是:使用Interlope服务,使用.com.和regasm,使用PInvoke(似乎只从C#到C++),并在C++/CLR中使用IJW(看起来像是Interlope服务).我认为最好设置一个库,它可能是一个CLR包装器,它使用IJW代表本机C++和C代码调用我的C#dll.
细节:我需要将来自c ++代码的string和int的值传递给C#dll,并返回void.
相关性:许多公司有很多借口来混合和匹配C++,C和C#.性能:非托管代码通常更快,接口:托管接口通常更易于维护,部署,并且通常更容易看到,管理员也告诉我们.遗产代码也迫使我们.它就在那里(就像我们爬过的山一样).虽然如何从C#调用C++库的示例很丰富.如何通过Google搜索很难找到如何从C++代码调用C#库的示例,尤其是如果您想要查看更新的4.0+代码.
软件: C#,C++/CLR,C++,C,Visual Studio 2010和.NET 4.0
问题详情:好的多部分问题:
使用com对象有优势吗?还是PInvoke?还是其他一些方法?(我觉得这里的学习曲线同样陡峭,尽管我确实在Google Land中找到了有关该主题的更多信息.IJW似乎承诺我想要它做什么.我应该放弃寻找IJW解决方案和转而专注于此?)(优势/劣势?)
我是否正确想象有一个解决方案,我在C++/CLR中编写了一个利用IJW的包装器?我在哪里可以找到关于这个主题的更多信息,并且没有说我没有足够的Google /或者在没有告诉我你在那里看到它的情况下查看MSDN.(我想我更喜欢这个选项,努力编写清晰简单的代码.)
问题范围缩小:我觉得我的真正问题和需求是回答下面的小问题:如何设置一个非托管C++文件可以在visual studio中使用的C++/CLR库.我认为,如果我可以简单地在非托管C++代码中实例化托管C++类,那么我可能能够解决其余的问题(接口和包装等).我希望我的主要愚蠢是尝试在Visual Studio中设置引用/ #include等,我想可以有其他误解.也许这整个问题的答案可能只是一个教程或指令的链接,可以帮助我解决这个问题.
研究:我一遍又一遍地用谷歌搜索和Binged取得了一些成功.我找到了许多链接,向您展示如何使用C#代码中的非托管库.我承认有一些链接显示如何使用com对象.针对VS 2010的结果并不多.
参考文献: 我已经阅读了很多帖子.我试图解决最相关的问题.有些人似乎非常接近答案,但我似乎无法让他们工作.我怀疑我遗漏的东西非常小,比如滥用关键字ref,或者缺少#include或者使用语句,或者滥用命名空间,或者没有正确使用IJW功能,或者缺少VS的设置需要正确处理编译等.所以你想知道,为什么不包括代码?好吧,我觉得我不在我理解的地方,并期望我必须工作的代码.我想要在一个我理解的地方,当我到达那里时,我可能需要帮助修复它.我将随机包含两个链接,但我不允许在我当前的Hitpoint级别显示所有链接.
http://www.codeproject.com/Articles/35437/Moving-Data-between-Managed-Code-and-Unmanaged-Cod
这从两个方向调用托管和非托管代码的代码,从C++到Visual Basic,然后通过C++ CLR返回,当然我对C#感兴趣:http://www.codeproject.com/Articles/9903/Calling -managed码-从-非托管代码和副
这些是Person类的声明.
protected int ID { get; set; }
protected string Title { get; set; }
protected string Description { get; set; }
protected TimeSpan jobLength { get; set; }
Run Code Online (Sandbox Code Playgroud)
我如何使用get/set?主要是,我实例化了一个
Person Tom = new Person();
Run Code Online (Sandbox Code Playgroud)
Tom.set/get怎么样?
我习惯于做C++风格,你只需写出int getAge()和void setAge()函数.但是在C#中有快捷方式处理get和set?
我有一组元素/键,我正在从两个不同的配置文件中读取.因此,键可以是相同的,但具有与它们中的每一个相关联的不同值.
我想按排序顺序列出它们.我能做什么 ?我尝试了SortedList类,但它不允许重复键.
我该怎么做?
例如,假设我有3个元素,键1,2,3.然后我得到一个具有键2(但值不同)的元素.然后我希望新密钥在现有密钥2之后但在3之前插入.如果我在找到一个带有密钥2的元素,那么它应该在最近添加的密钥2之后.
请注意,我使用的是.NET 2.0
我现在明白"Inno Setup可以为您执行命令行工具,而无需使用批处理文件." (Inno安装程序可以安装Windows安全组吗?)它能够做到这一点是有意义的.从我到目前为止的网络搜索到Inno Setup,我找不到一个了解如何做到这一点的起点.一个完整的答案可能没有必要,如果我只是进一步暗示要寻找什么,那可能就足够了.
自从我上次在Pascal写作以来已经有20年了.我似乎无法正确使用语言的结构元素,而不是使用begin和end的块.例如,这给我一个编译器错误"标识符预期"
procedure InitializeWizard;
begin
Log('Initialize Wizard');
if IsAdminLoggedOn then begin
SetupUserGroup();
SomeOtherProcedure();
else begin (*Identifier Expected*)
Log('User is not an administrator.');
msgbox('The current user is not administrator.', mbInformation, MB_OK);
end
end;
end;
Run Code Online (Sandbox Code Playgroud)
当然,如果我删除if then块和begin与它们相关的块,那么一切都OK.
有时我会得到这种语法,并且它可以正常运行,但是在嵌套end块时问题会变得恼怒.
解决这个问题还不够.我想更好地了解如何使用这些块.我显然错过了一个概念.来自C++或C#的东西可能正在从我的另一部分中悄悄进入并弄乱我的理解.我已经阅读了一些关于它的文章,我认为我理解它然后我没有.
当您在没有安装Visual Studio 2010的计算机上安装Visual Studio 2012时(我认为),会出现此问题.我想在Visual Studio 2012上构建目标.net 4.0.我已经在没有VisualStudo 2010的情况下设置了机器.我最终得到的信息如下:
*Warning 2 The primary reference "blablaLibraryproject" could not be resolved because it was built against the ".NETFramework,Version=v4.5" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.0". blablaExecutableproject*
Run Code Online (Sandbox Code Playgroud)
这里的回答帖子(安装了.NET 4.5的构建服务器能否成功将面向4.0的项目部署到仅安装了.NET 4.0的服务器?)说:
您可以更正此问题,但是您需要将4.0引用程序集添加到构建服务器(以便编译器找到它们),而不仅仅依赖于.NET 4.5版本.
那么你如何" 将4.0引用程序集添加到构建服务器(以便编译器找到它们) "?
我正在看一些c ++代码,我看到:
byte b = someByteValue;
// take twos complement
byte TwosComplement = -b;
Run Code Online (Sandbox Code Playgroud)
这段代码是否采用b的两个补码?如果没有,它在做什么?
因此,给定此功能,我GetRoot := ROOTPage.Values[0];在行上收到错误"Identifier Expected" .我希望它告诉我ROOTPage没有定义?
const
DefaultRoot = 'C:\IAmGRoot';
Var
ROOTPage : TInputQueryWizardPage;
procedure SetupRoot;
begin
ROOTPage := CreateInputQueryPage(wpUserInfo,
ExpandConstant('{cm:RootTitle}'),
ExpandConstant('{cm:RootInstructions}'),
ExpandConstant('{cm:RootDescription}') + ' "' + DefaultRoot + '"'
);
ROOTPage.Add(ExpandConstant('{cm:SSRoot}') + ':', False);
ROOTPage.Values[0] := ExpandConstant('{DefaultRoot}');
// add SSROOT to path
end;
function GetRoot : string;
begin
GetRoot := ROOTPage.Values[0];
end;
Run Code Online (Sandbox Code Playgroud)
我该如何解释这个错误.Pascal中的标识符是什么?
这个页面告诉我标识符是变量名.也许我需要以ROOTPage.Values[0]某种方式扩展它,因为我从Inno Setup对象引用一个数组?
或许我需要以不同的方式返回值.我在Pascal上看到一个页面表示你需要避免在参数较少的函数上分配函数值以避免递归循环.这是否意味着我应该传递一个虚拟值?还是有不同的语法?该页面没有解释.
我暗自认为我的真正问题是我没有正确定义我的功能......但是很好.这至少可以编译.这个问题可能变成:你如何在Pascal中处理无参数函数?
我不认为Inno Setup是问题的一部分,但我正在与Inno Setup合作以防万一.
更新: 它似乎不是数组,因为它得到相同的错误:
const
DefaultRoot = 'C:\IAmGRoot';
function GetRoot : …Run Code Online (Sandbox Code Playgroud) 所以我想的是一个类的实例,我想要一个线程在类的生命周期中运行,但是当调用类的进程不再运行时终止.这不是父线程终止子进程的情况,而是单个旋转(在等待循环中)线程正常退出而不保留资源等.
我认为在C++中,你可以告诉线程使用析构函数中的volatile bool来终止,但是在C#中,〜不是析构函数,它是终结器.我无法使用终结器成功终止线程.也许我错过了一些东西.我知道更好的做法是让所有线程死于自然死亡而不发出信号终止,但每次我需要做某事时产生一个线程效率都不高.是的我知道线程池,但我认为让一个侦听器线程响应对类的调用会更好,并且当类放在gc上时它会优雅地死掉.
真的诀窍是,我想,我可以知道,或者我怎么知道什么时候运行该线程的类首先放在gc上.IDisispos是我想要的吗?我这里没有使用任何非托管代码.
我很好奇,通过谷歌研究,我一直在学习数字签名和强烈命名的程序集.如果您真的努力,似乎可以使用数字签名来签署强名称的程序集.
我推测,通过这种做法,可以通过这种方式使用它来规避数字签名的目的.
微软说:
"强名称本身并不意味着一种信任程度,例如通过数字签名和支持证书提供的信任."
- http://msdn.microsoft.com/en-us/library/wd40t7ad%28v=vs.110%29.aspx
我是否正确地猜测以这种方式使用数字签名实际上是一种不好的做法,这可能会造成安全漏洞并且绝对没有用处?或者甚至可能吗?使用数字签名作为强名称可能或更好然后什么都不做?除了正确使用数字签名之外,它是否提供了额外的安全性.
c# ×6
inno-setup ×3
c++ ×2
pascalscript ×2
syntax ×2
.net-2.0 ×1
.net-4.0 ×1
byte ×1
c#-4.0 ×1
c++-cli ×1
delphi ×1
finalizer ×1
function ×1
generic-list ×1
pascal ×1
properties ×1
strongname ×1