#include "com/fikom_nesne.hpp" namespace fikatia { namespace { std::string dar(const std::wstring& w) { if (w.empty()) return {}; const int n = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), nullptr, 0, nullptr, nullptr); std::string s(n, '\0'); WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), s.data(), n, nullptr, nullptr); return s; } [[noreturn]] void hataAt(const wchar_t* ad, const char* asama, HRESULT hr) { _com_error ce(hr); throw FikomHata("CATIA çağrısı başarısız: " + dar(ad) + " (" + std::string(asama) + "): " + (ce.ErrorMessage() ? dar(ce.ErrorMessage()) : "?"), static_cast(hr)); } } // namespace FikomNesne& FikomNesne::operator=(const FikomNesne& o) { if (this == &o) return *this; if (o.p_) o.p_->AddRef(); if (p_) p_->Release(); p_ = o.p_; return *this; } FikomNesne& FikomNesne::operator=(FikomNesne&& o) noexcept { if (this == &o) return *this; if (p_) p_->Release(); p_ = o.p_; o.p_ = nullptr; return *this; } [[nodiscard]] _variant_t FikomNesne::cagir(unsigned short tur, const wchar_t* ad, std::vector<_variant_t>* args) const { if (!p_) throw FikomHata(std::string("Boş COM nesnesi üzerinde çağrı: ") + dar(ad), 0); DISPID kimlik = DISPID_UNKNOWN; LPOLESTR adPtr = const_cast(ad); HRESULT hr = p_->GetIDsOfNames(IID_NULL, &adPtr, 1, LOCALE_USER_DEFAULT, &kimlik); if (FAILED(hr)) hataAt(ad, "isim", hr); DISPPARAMS dp{}; // COM kuralı: argümanlar Invoke'a ters sırada dizilir. std::vector ters; if (args && !args->empty()) { ters.reserve(args->size()); for (auto it = args->rbegin(); it != args->rend(); ++it) ters.push_back(*it); dp.rgvarg = ters.data(); dp.cArgs = static_cast(ters.size()); } DISPID putKimlik = DISPID_PROPERTYPUT; if (tur == DISPATCH_PROPERTYPUT) { dp.rgdispidNamedArgs = &putKimlik; dp.cNamedArgs = 1; } _variant_t sonuc; EXCEPINFO ei{}; UINT hataArg = 0; hr = p_->Invoke(kimlik, IID_NULL, LOCALE_USER_DEFAULT, tur, &dp, &sonuc, &ei, &hataArg); if (FAILED(hr)) { if (ei.bstrDescription) { std::string m = "CATIA hatası: " + dar(ad) + ": " + dar(ei.bstrDescription); SysFreeString(ei.bstrDescription); if (ei.bstrSource) SysFreeString(ei.bstrSource); if (ei.bstrHelpFile) SysFreeString(ei.bstrHelpFile); throw FikomHata(m, static_cast(hr)); } hataAt(ad, "çağrı", hr); } return sonuc; } [[nodiscard]] _variant_t FikomNesne::ozellik(const wchar_t* ad) const { return cagir(DISPATCH_PROPERTYGET, ad, nullptr); } void FikomNesne::ozellikAyarla(const wchar_t* ad, const _variant_t& deger) { std::vector<_variant_t> args{deger}; cagir(DISPATCH_PROPERTYPUT, ad, &args); } [[nodiscard]] _variant_t FikomNesne::metod(const wchar_t* ad, std::vector<_variant_t> args) { // CATIA'da bazı "metodlar" property-get olarak da çağrılabilir; önce metod dene. return cagir(DISPATCH_METHOD | DISPATCH_PROPERTYGET, ad, &args); } [[nodiscard]] FikomNesne FikomNesne::nesne(const wchar_t* ad) const { _variant_t v = ozellik(ad); return varyantNesne(v); } [[nodiscard]] std::wstring FikomNesne::metin(const wchar_t* ad) const { _variant_t v = ozellik(ad); if (v.vt == VT_EMPTY || v.vt == VT_NULL) return {}; v.ChangeType(VT_BSTR); return v.bstrVal ? std::wstring(v.bstrVal) : std::wstring(); } [[nodiscard]] long FikomNesne::sayi(const wchar_t* ad) const { _variant_t v = ozellik(ad); v.ChangeType(VT_I4); return v.lVal; } [[nodiscard]] FikomNesne FikomNesne::eleman(long indeks) const { std::vector<_variant_t> args{_variant_t(indeks)}; _variant_t v = const_cast(this)->cagir( DISPATCH_METHOD | DISPATCH_PROPERTYGET, L"Item", &args); return varyantNesne(v); } [[nodiscard]] FikomNesne varyantNesne(_variant_t& v) { if (v.vt == VT_DISPATCH && v.pdispVal) { IDispatch* p = v.pdispVal; p->AddRef(); // _variant_t yıkımında kendi ref'ini bırakır return FikomNesne(p); } if (v.vt == VT_UNKNOWN && v.punkVal) { IDispatch* p = nullptr; if (SUCCEEDED(v.punkVal->QueryInterface(IID_IDispatch, reinterpret_cast(&p)))) { return FikomNesne(p); } } return {}; } } // namespace fikatia