클라이언트와 서버 모두 C#에서 C ++ COM 인터페이스 사용
문제
모든 종류의 구현과 함께 COM을 통해 C# 코드를 상호 작용해야합니다.
해당 통합 사용자에게 쉽게하기 위해 IDL에 상호 작용 된 인터페이스를 포함 시켰지만 (관련 기존 DLL의 일부이지만 Coclass 또는 구현이 없음) TLBimp를 실행하여 유형 정의를 만들어 C# 코드로 가져 왔습니다.
C#을 구현하고 Windows 레지스트리 정보를 기반으로 COM 객체를 작성하고 필요한 인터페이스에 객체를 캐스팅했습니다.
그런 다음 별도 프로젝트에서 인터페이스의 C# 구현을 만들어 등록했습니다. 기본 프로그램은 테스트 COM 객체를 올바르게 생성하지만 인터페이스에 캐스팅하지 못합니다 (C# 'AS'를 사용할 때 널 객체를 가져 와서 명시 적 캐스트에 대한 잘못된 캐스트 소지를 가져옵니다).
인터페이스가 테스트 객체에서 구현 된 것으로 식별되지 않는 이유를 누군가에게 제안 할 수 있습니까?
이것은 IDL의 인터페이스 결함입니다 (2005 년 C ++에서 컴파일) :
[
object,
uuid(B60C546F-EE91-48a2-A352-CFC36E613CB7),
dual,
nonextensible,
helpstring("IScriptGenerator Interface"),
pointer_default(unique)
]
interface IScriptGenerator : IDispatch{
[helpstring("Init the Script generator")]
HRESULT Init();
[helpstring("General purpose error reporting")]
HRESULT GetLastError([out] BSTR *Error);
};
이것은 tlbimp에 의해 c#을 위해 만든 스터브입니다.
[TypeLibType(4288)]
[Guid("B60C546F-EE91-48A2-A352-CFC36E613CB7")]
public interface IScriptGenerator
{
[DispId(1610743813)]
void GetLastError(out string Error);
[DispId(1610743808)]
void Init();
}
이것은 기본 C# 코드의 일부이며, 프로로드에 의해 COM 객체를 생성하고 iscriptGenerator 인터페이스에 캐스팅합니다.
public ScriptGenerator(string GUID)
{
Type comType = Type.GetTypeFromProgID(GUID);
object comObj = null;
if (comType != null)
{
try
{
comObj = Activator.CreateInstance(comType);
}
catch (Exception ex)
{
Debug.Fail("Cannot create the script generator COM object due to the following exception: " + ex, ex.Message + "\n" + ex.StackTrace);
throw ex;
}
}
else
throw new ArgumentException("The GUID does not match a registetred COM object", "GUID");
m_internalGenerator = comObj as IScriptGenerator;
if (m_internalGenerator == null)
{
Debug.Fail("The script generator doesn't support the required interface - IScriptGenerator");
throw new InvalidCastException("The script generator with the GUID " + GUID + " doesn't support the required interface - IScriptGenerator");
}
}
그리고 이것은 작동중인 C# 코드 구현입니다.
[Guid("EB46E31F-0961-4179-8A56-3895DDF2884E"),
ProgId("ScriptGeneratorExample.ScriptGenerator"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(SOAAPIOLELib.IScriptGeneratorCallback))]
public class ScriptGenerator : IScriptGenerator
{
public void GetLastError(out string Error)
{
throw new NotImplementedException();
}
public void Init()
{
// nothing to do
}
}
해결책
다시 한 번 - 제안해 주셔서 감사합니다.
나는 마침내 스스로 문제를 해결할 수있었습니다. 나는 위의 제안을 시도했지만 아무런 진전도하지 않았다. 그런 다음 '테스트'코드에서 Interop의 네임 스페이스를 변경했습니다. TLBIMP를 사용할 때 다른 인수 사용으로 인해 기본 코드의 코드마다 다릅니다. 이것은 문제를 해결했습니다.
.NET은 COM 객체를 생성하지만 실제로 .NET 객체 인 경우 COM 레이어를 우회하고 직접 통신합니다. 이 경우 QueryInterface (Interface Guid 포함)를 사용하지 않으며 C# 네임 스페이스가 다른 경우 인터페이스가 다릅니다.
이는 .NET 코드와 통합을 지원하려면 IDL을 제외하고 원래 Interop 어셈블리를 게시해야합니다.
감사합니다, Inbar
다른 팁
인터페이스에서 이것을 필요로한다고 생각합니다
[InterfaceType(ComInterfaceType.InterfaceIsDual)]