我的IDL:
[
object,
uuid(52D64BCC-03F1-442B-BED1-70992111E2B1),
helpstring("ISimpleObject Interface"),
pointer_default(unique)
]
interface ISimpleObject : IUnknown{
[helpstring("method Hoop"), local] HRESULT Hoop(void);
};
[
uuid(3D9ABD55-3C84-43C8-9C34-3915B6B34989),
version(1.0),
helpstring("ComServer 1.0 Type Library")
]
library ComServerLib
{
importlib("stdole2.tlb");
[
uuid(42E2236D-1DA0-455F-9EF4-31A4A1E04F47),
helpstring("SimpleObject Class")
]
coclass SimpleObject
{
[default] interface ISimpleObject;
};
};
我的COM课程:
class ATL_NO_VTABLE CSimpleObject :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSimpleObject, &CLSID_SimpleObject>,
public ISimpleObject
{
public:
CSimpleObject()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLEOBJECT)
BEGIN_COM_MAP(CSimpleObject)
COM_INTERFACE_ENTRY(ISimpleObject)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
// ISimpleObject
STDMETHOD(Hoop)(void)
{
return S_OK;
}
};
OBJECT_ENTRY_AUTO(__uuidof(SimpleObject), CSimpleObject)
我的.NET客户端:
[ComImport]
[Guid("52D64BCC-03F1-442B-BED1-70992111E2B1")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISimpleObject
{
[PreserveSig]
int Hoop();
}
[ComImport]
[Guid("42E2236D-1DA0-455F-9EF4-31A4A1E04F47")]
public class SimpleObject
{
}
class Program
{
static void Main(string[] args)
{
SimpleObject simpleObject = new SimpleObject();
ISimpleObject simpleObjectInterface = (ISimpleObject)simpleObject;
int returnValue = simpleObjectInterface.Hoop(); // Error!
}
}
客户端获得异常“System.AccessViolationException:试图读取或写入受保护的内存......”。为什么呢?
我正在使用Visual Studio 2008,Windows Vista x64。 C ++和C#项目有x86配置。
答案 0 :(得分:0)
int Hoop();
是将IDL声明错误地翻译成C#。 正确的是
void Hoop();
.NET将COM结果代码(HRESULT)包装到对应的C#异常中。例如,如果在C ++代码中返回E_NOTIMPL,则.NET运行时将抛出NotImplementedException类的实例
*的 更新 * 强>
根据MSDN,主应用程序线程默认初始化为“MTA”。您的对象CSimpleObject配置为驻留在“STA”中。为了进行交叉分离调用,COM运行时将使用your implementation of the proxy/stub to marshall相应的数据。
运行时需要一个有效的代理/存根实现,它由MIDL从您的IDL文件生成。
您已将“Hoop”功能标记为“Local”。这意味着MIDL不会为此方法生成任何编组代码,这就是您获得异常的原因。
应该删除'local'属性,因为它被设计为仅在实现对象的服务器内使用。 但作为一种可能的解决方案,我建议您使用配置为在STA中运行的线程中的对象。无论如何,这是一种糟糕的方法,因为它不能保证不会涉及编组。
您可以将主线程标记为在STA中运行,如下所示:
[STAThread()]
static void Main(string[] args)
{
...
}
我希望这可以帮助您解决问题。