如何从非STA线程和/或64位进程使用C#中的32位COM库 我试图在C++应用程序中使用一个遗留的COM组件(可能是C++中创建的DLL库,32位)。我需要让它在以下情况下工作: x86 STA线程中使用的COM组件(例如主应用程序线程) x86工作线程中使用的COM组件(例如任务/线程池) x64 STA线程中使用的COM组件(例如主应用程序线程) x64工作线程中使用的COM组件(例如任务/线程池)
到目前为止,我已经在场景1中使用了它。我还为场景2创建了PoC包装器——但这不是我现在想要遵循的方式。总而言之,只有场景1可以正常工作。其余的根本没有 我做了一些研究,发现情景1应该相当简单。的确如此。我还了解到,当COM组件托管在代理(32位?)进程中时,场景2、3、4也应该是可能的。在这种情况下,可能会出现严重的性能损失,但我现在不太关心性能 虽然我试了很多次,但都没能成功。我已经没有主意了,需要你的帮助。 让我先描述一下我的设置。开头提到的COM组件作为以下一组文件提供:如何从非STA线程和/或64位进程使用C#中的32位COM库 我试图在C++应用程序中使用一个遗留的COM组件(可能是C++中创建的DLL库,32位)。我需要让它在以下情况下工作: x86 STA线程中使用的COM组件(例如主应用程序线程) x86工作线程中使用的COM组件(例如任务/线程池) x64 STA线程中使用的COM组件(例如主应用程序线程) x64工作线程中使用的COM组件(例如任务/线程池),c#,dll,com,interop,regsvr32,C#,Dll,Com,Interop,Regsvr32,到目前为止,我已经在场景1中使用了它。我还为场景2创建了PoC包装器——但这不是我现在想要遵循的方式。总而言之,只有场景1可以正常工作。其余的根本没有 我做了一些研究,发现情景1应该相当简单。的确如此。我还了解到,当COM组件托管在代理(32位?)进程中时,场景2、3、4也应该是可能的。在这种情况下,可能会出现严重的性能损失,但我现在不太关心性能 虽然我试了很多次,但都没能成功。我已经没有主意了,需要你的帮助。 让我先描述一下我的设置。开头提到的COM组件作为以下一组文件提供: GeoDefs
- GeoDefs.dll
- GeoDefs.tlb
- GeomDefs.dll
- GeomDefs.tlb
- GeoFunc.dll
- GeoFunc.tlb
- GeomFunc.dll
- GeomFunc.tlb
- GeoDatumKrtgrf.dll
- GeoDatumKrtgrf.tlb
- GeoDatumKrtgrf 1.0类型库
- GeoDefs 1.0类型库
- GeoFunc 1.0类型库
- GeomDefs 1.0类型库
- GeomFunc 1.0类型库
- Interop.GEODATUMKRTGRFLib.dll
- Interop.GEODEFSLib.dll
- Interop.GEOFUNCLib.dll
- Interop.geomeDefslib.dll
- Interop.GEOMFUNCLib.dll
- 地理坐标KRTGRFLB
- 大地裂缝
- 地理功能库
- 土工格栅
- 几何函数库
void btnComInMainThread_Click(object sender, EventArgs e)
{
try
{
var comObject = new GeoDatumKrtgrfClass();
comObject.InitDatum(eT_DatumTypes.DT_WGS_1984);
comObject.LG2G(out var lonDouble, out var latDouble, 17000000, 25000000);
Debug.Assert(Math.Abs(lonDouble - 17.0) < 1e-6 && Math.Abs(latDouble - 25.0) < 1e-6);
Debug.Print($"{DateTime.Now:HH:mm:ss.fff}: Ok.");
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
}
void btnComInWorkerThread_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
try
{
var comObject = new GeoDatumKrtgrfClass();
comObject.InitDatum(eT_DatumTypes.DT_WGS_1984);
comObject.LG2G(out var lonDouble, out var latDouble, 17000000, 25000000);
Debug.Assert(Math.Abs(lonDouble - 17.0) < 1e-6 && Math.Abs(latDouble - 25.0) < 1e-6);
Debug.Print($"{DateTime.Now:HH:mm:ss.fff}: Ok.");
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
});
}
下面我将包括一些来自OLE/COM对象查看器和ILSpy的(缩短的)额外信息
GeoDatumKrtgrf.tlb
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: GeoDatumKrtgrf.tlb
[
uuid(D541177E-570B-4F7F-A6B0-931C0BAC85C9),
version(1.0),
helpstring("GeoDatumKrtgrf 1.0 Type Library"),
custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663662),
custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1302262921),
custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 6.00.0366 at Fri Apr 08 13:41:58 2011
")
]
library GEODATUMKRTGRFLib
{
// TLib : // TLib : GeoDefs 1.0 Type Library : {3EB9DBAA-44B4-4FFE-AAA2-FA7AFC6FC228}
importlib("GeoDefs.tlb");
// TLib : GeomDefs 1.0 Type Library : {F28B71EA-132F-4C47-AAB1-1218716945E5}
importlib("GeomDefs.tlb");
// Forward declare all types defined in this typelib
interface IGeoDatumKrtgrf;
[
uuid(7948C0A1-0806-406A-B5A1-34A9106B8C37),
helpstring("GeoDatumKrtgrf Class")
]
coclass GeoDatumKrtgrf {
[default] interface IGeoDatumKrtgrf;
};
[
odl,
uuid(C6ACFB21-24DC-43FB-AF7F-07EB526D2DF5),
helpstring("IGeoDatumKrtgrf Interface")
]
interface IGeoDatumKrtgrf : IGeoDatum {
...
[helpstring("method LG2G")]
HRESULT _stdcall LG2G(
[out] double* pd_Lon,
[out] double* pd_Lat,
[in] long l_Lon,
[in] long l_Lat);
...
};
};
GeoDefs.tlb
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: GeoDefs.tlb
[
uuid(3EB9DBAA-44B4-4FFE-AAA2-FA7AFC6FC228),
version(1.0),
helpstring("GeoDefs 1.0 Type Library"),
custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663662),
custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1302262808),
custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 6.00.0366 at Fri Apr 08 13:40:05 2011
")
]
library GEODEFSLib
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
...
[
odl,
uuid(69E77C75-BB8D-46F9-BD93-1D26E09249DE),
helpstring("IGeoDatum Interface")
]
interface IGeoDatum : IUnknown {
HRESULT _stdcall InitDatum([in] eT_DatumTypes e_Datum);
HRESULT _stdcall SetViewByR(
[in] stT_GeoRect* pst_GeoRect,
[in, out] tagRECT* pst_Rect);
HRESULT _stdcall SetViewByP(
[in] stT_GeoCoord* pst_GeoCoordLB,
[in] stT_GeoCoord* pst_GeoCoordRT,
[in, out] tagPOINT* pst_PntLB,
[in, out] tagPOINT* pst_PntRT);
HRESULT _stdcall G2L(
[in] double d_Lon,
[in] double d_Lat,
[in, out] long* pl_X,
[in, out] long* pl_Y);
HRESULT _stdcall L2G(
[in] long l_X,
[in] long l_Y,
[in, out] double* pd_Lon,
[in, out] double* pd_Lat);
HRESULT _stdcall GP2LP(
[in] stT_GeoCoord* pst_GeoCoord,
[in, out] tagPOINT* pst_Pnt);
HRESULT _stdcall LP2GP(
[in] tagPOINT* pst_Pnt,
[in, out] stT_GeoCoord* pst_GeoCoord);
HRESULT _stdcall GR2LR(
[in] stT_GeoRect* pst_GeoRect,
[in, out] tagRECT* pst_Rect);
HRESULT _stdcall LR2GR(
[in] tagRECT* pst_Rect,
[in, out] stT_GeoRect* pst_GeoRect);
[helpstring("method NormalizeGR")]
HRESULT _stdcall NormalizeGR([in, out] stT_GeoRect* pst_GeoRect);
};
...
[
uuid(38EE7367-30EC-43A7-96F6-C55BC39B62C0),
helpstring("Cnv Class")
]
coclass Cnv {
[default] interface ICnv;
};
[
odl,
uuid(6C92FACA-266F-4943-B4AE-7E538F6FC672),
helpstring("ICnv Interface")
]
interface ICnv : IUnknown {
[helpstring("method dms2dd")]
HRESULT _stdcall dms2dd(
[in] stT_GeoCoordDMS* pst_GeoCoordDMS,
[out, retval] stT_GeoCoord* pst_GeoCoord);
[helpstring("method dd2dms")]
HRESULT _stdcall dd2dms(
[in] stT_GeoCoord* pst_GeoCoord,
[out, retval] stT_GeoCoordDMS* pst_GeoCoordDMS);
[helpstring("method dm2dd")]
HRESULT _stdcall dm2dd(
[in] stT_GeoCoordDM* pst_GeoCoordDM,
[out, retval] stT_GeoCoord* pst_GeoCoord);
[helpstring("method dd2dm")]
HRESULT _stdcall dd2dm(
[in] stT_GeoCoord* pst_GeoCoord,
[out, retval] stT_GeoCoordDM* pst_GeoCoordDM);
[helpstring("method DDMMSS2d")]
HRESULT _stdcall DDMMSS2d(
[out] stT_GeoCoord* pst_GeoCoord,
[in] long l_Lon,
[in] long l_Lat);
[helpstring("method d2DDMMSS")]
HRESULT _stdcall d2DDMMSS(
[out] long* pl_Lon,
[out] long* pl_Lat,
[in] stT_GeoCoord* pst_GeoCoord);
[helpstring("method dmsTodd")]
HRESULT _stdcall dmsTodd(
[in] stT_GeoCoordDMS* pst_GeoCoordDMS,
[out] stT_GeoCoord* pst_GeoCoord);
[helpstring("method ddTodms")]
HRESULT _stdcall ddTodms(
[in] stT_GeoCoord* pst_GeoCoord,
[out] stT_GeoCoordDMS* pst_GeoCoordDMS);
[helpstring("method dmshToddh")]
HRESULT _stdcall dmshToddh(
[in] stT_GeoCoordDMSH* pst_GeoCoordDMSH,
[out] stT_GeoCoordH* pst_GeoCoordH);
[helpstring("method ddhTodmsh")]
HRESULT _stdcall ddhTodmsh(
[in] stT_GeoCoordH* pst_GeoCoordH,
[out] stT_GeoCoordDMSH* pst_GeoCoordDMSH);
[helpstring("method dd2ch")]
HRESULT _stdcall dd2ch(
[in] stT_GeoCoord* pst_GeoCoord,
[out] BSTR* pac_Lat,
[out] BSTR* pac_Lon);
};
};
Interop.GEODATUMKRTGRFLib.dll 1/3
// GEODATUMKRTGRFLib.GeoDatumKrtgrfClass
using GEODATUMKRTGRFLib;
using GEODEFSLib;
using GEOMDEFSLib;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[ComImport]
[ClassInterface(0)]
[TypeLibType(2)]
[Guid("7948C0A1-0806-406A-B5A1-34A9106B8C37")]
public class GeoDatumKrtgrfClass : IGeoDatumKrtgrf, GeoDatumKrtgrf
{
[MethodImpl(MethodImplOptions.InternalCall)]
public extern GeoDatumKrtgrfClass();
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern void InitDatum([In] eT_DatumTypes e_Datum);
void IGeoDatumKrtgrf.InitDatum([In] eT_DatumTypes e_Datum)
{
//ILSpy generated this explicit interface implementation from .override directive in InitDatum
this.InitDatum(e_Datum);
}
...
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern void LG2G(out double pd_Lon, out double pd_Lat, [In] int l_Lon, [In] int l_Lat);
void IGeoDatumKrtgrf.LG2G(out double pd_Lon, out double pd_Lat, [In] int l_Lon, [In] int l_Lat)
{
//ILSpy generated this explicit interface implementation from .override directive in LG2G
this.LG2G(out pd_Lon, out pd_Lat, l_Lon, l_Lat);
}
...
}
Interop.GEODATUMKRTGRFLib.dll 2/3
// GEODATUMKRTGRFLib.IGeoDatumKrtgrf
using GEODEFSLib;
using GEOMDEFSLib;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[ComImport]
[Guid("C6ACFB21-24DC-43FB-AF7F-07EB526D2DF5")]
[InterfaceType(1)]
public interface IGeoDatumKrtgrf : IGeoDatum
{
[MethodImpl(MethodImplOptions.InternalCall)]
new void InitDatum([In] eT_DatumTypes e_Datum);
...
[MethodImpl(MethodImplOptions.InternalCall)]
void LG2G(out double pd_Lon, out double pd_Lat, [In] int l_Lon, [In] int l_Lat);
...
}
Interop.GEODATUMKRTGRFLib.dll 3/3
// GEODATUMKRTGRFLib.GeoDatumKrtgrf
using GEODATUMKRTGRFLib;
using System.Runtime.InteropServices;
[ComImport]
[Guid("C6ACFB21-24DC-43FB-AF7F-07EB526D2DF5")]
[CoClass(typeof(GeoDatumKrtgrfClass))]
public interface GeoDatumKrtgrf : IGeoDatumKrtgrf
{
}
Interop.GEODEFSLib.dll
// GEODEFSLib.IGeoDatum
using GEODEFSLib;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[ComImport]
[Guid("69E77C75-BB8D-46F9-BD93-1D26E09249DE")]
[InterfaceType(1)]
public interface IGeoDatum
{
[MethodImpl(MethodImplOptions.InternalCall)]
void InitDatum([In] eT_DatumTypes e_Datum);
...
}
还有Cnv、CnvClass和ICnv(以及许多结构和枚举),它们似乎不太相关,目前不包括在内
说到以上,我想补充一点,我还试图手动调整系统注册表。它相当混乱,没有带来任何改善
我希望您能帮助我运行所有四种方案。不,这是行不通的。周围有很多地理库,是时候让这一个满足它的制造商了。@HansPassant为了简单起见,我把重点放在了地理计算上。我同意,典型的地质计算方法很容易替换。但是,在某些地方,这些库中只包含简单的计算(例如,某些方法生成固定大小的小型位图图形)。更重要的是,我们并不总是知道用于产生结果的算法。如果有机会找到一个解决方案并使其全部运行,那就太好了。
// GEODEFSLib.IGeoDatum
using GEODEFSLib;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[ComImport]
[Guid("69E77C75-BB8D-46F9-BD93-1D26E09249DE")]
[InterfaceType(1)]
public interface IGeoDatum
{
[MethodImpl(MethodImplOptions.InternalCall)]
void InitDatum([In] eT_DatumTypes e_Datum);
...
}