Aracılığıyla paylaş


Karışık Derlemeleri Başlatma

Visual C++.NET ve Visual C++ 2003'te, /clr derleyici seçeneği ile derlenmiş DLL dosyaları yüklendiğinde kararsız biçimde kilitlenebiliyordu, bu soruna karışık DLL yükleme veya yükleyici kilidi kilitlenmesi deniyordu. Neredeyse tüm gerekircilik dışılıklar, karışık DLL yükleme işleminden kaldırıldı. Ancak, hangi yükleyici kilidinin (kesin olarak) oluşabileceği ile ilgili birkaç senaryo daha vardır. Bu sorun hakkında daha fazla bilgi için MSDN Kitaplığı'ndaki "Karma DLL Yükleme Sorunu" konusuna bakın.

DllMain içerisindeki kod CLR'ye erişmemelidir. Buna göre DllMain yönetilen işlevlerle dolaylı veya dolaysız hiç bir çağrıda bulunmamalıdır; hiç bir yönetilen kod DllMain öğesinde bildirilmemeli veya uygulanmamalıdır ve DllMain içinde hiç bir atık toplama veya otomatik kitaplık yüklemesi oluşmamalıdır.

Not

Visual C++ 2003 kilitlenme ihtimalini en aza indirirken, DLL başlatmayı kolaylaştırmak için _vcclrit.h sağlar._vcclrit.h kullanmak artık gerekli değildir ve derleme sırasında itiraz uyarıları oluşturulmasına neden olur.Önerilen strateji Removing Deprecated Header File _vcclrit.h öğesindeki adımları kullanarak bu dosyadaki bağımlılıkları kaldırmaktır.Daha az ideal çözümler, _vcclrit.h öğesini dahil etmeden önce _CRT_VCCLRIT_NO_DEPRECATE öğesini tanımlayarak uyarıları baskılamak veya yalnızca kullanımdan kalkma uyarılarını yok saymaktır.

Yükleyici Kilidinin Nedenleri

.NET platformunun girişi ile, yürütme modülü (EXE or DLL) yüklemeye ilişkin iki ayrı mekanizma vardır: Windows için yönetilmeyen modüllere ilişkin olarak kullanılan bir mekanizma ve .NET derlemelerini yükleyen .NET Ortak Dil Çalışma Zamanı (CLR) için bir mekanizma. Karışık DLL yükleme sorunu Microsoft Windows İşletim Sistemi yükleyicisi çevresinde toplanır.

Sadece .NET yapılarını içeren bir derleme bir işleme yüklendiğinde, CLR yükleyicisi tüm gerekli yükleme ve başlatma görevlerini kendisi yerine getirebilir. Ancak, karışık derlemeler için, yerel kod ve veriler de içerebildikleri için Windows yükleyicisi de kullanılmalıdır.

Windows yükleyicisi, başlatılmadan önce hiçbir kodun DLL öğesindeki koda veya veriye erişemeyeceğini ve kısmen başlatıldığında hiçbir kodun DLL öğesini gereksiz yere yükleyemeyeceğini garanti eder. Bunu yapmak için Windows yükleyicisi modül başlangıcı sırasında güvenli olmayan erişimi engelleyen bir işlem genel kritik bölüm (genellikle yükleyici kilidi olarak anılır) kullanır. Sonuç olarak, yükleme işlemi, klasik birçok kilitlenme senaryosuna karşı savunmasızdır. Karışık derlemelerde, aşağıdaki iki senaryo kilitlenme riski artırır:

  • Önce, Yükleyici kilidi tutulurken kullanıcıların Microsoft ara dili (MSIL) ile derlenmiş işlevleri yürütmeyi denemesi, (DllMain üzerinden veya statik başlatıcılar içinde, örneğin), bir çıkmaza neden olabilir. Yüklenmemiş bir derleme üzerinde bir MSIL işlevinin bir türü ifade ettiği bir durumu düşünün. CLR, yükleyici kilitte Windows yükleyici gerektirebilecek bu birleştirmeyi otomatik olarak yüklemeye çalışacaktır. Yükleyici kilidi çağrı sırasında kod tarafından zaten önceden tutulduğundan kilitlenme meydana gelir. Ancak MSIL'i yükleyici kilidi altında yürütmek bir kilitlenmenin oluşacağını garanti etmez, bu senaryoyu tanılamayı ve düzeltmeyi zorlaştırır. Bazı durumlarda, başvurulan türün DLL'si hiç bir yerel yapı barındırmadığında ve hiç bir bağımlılığı yerel yapı barındırmadığında, başvurulan türün.NET derlemesini yüklemek için Windows yükleyicisi gerekmez. Ayrıca, gerekli derleme veya onun karışık yerel/.NET bağımlılıkları, daha önce başka bir kod tarafından yüklenmiş olabilir. Sonuç olarak, kilitlenmenin öngörülmesi zor olabilir ve hedef makinenin yapılandırmasına bağlı olarak değişiklik gösterebilir.

  • İkinci olarak, NET Framework'ün 1.0 ve 1.1 sürümlerinden DLL'ler yüklerken, CLR yükleyici kilidin düzenlenmemiş olduğunu ve yükleyici kilit altında geçersiz olan birçok eylem uyguladığını varsayar. Karışık DLL'ler yerel başlatma yordamları yürüttüğünden "yükleyici kilidi kaldırılmıyor" önermesinin .NET DLL'leri açısından doğru bir önerme olduğunu varsayarsak, yerel Windows yükleyicisine ve dolayısıyla yükleyici kilidine gereksinim duyarlar. Sonuç olarak, geliştirici DLL başlatması sırasında MSIL işlevleri yürütme girişiminde olmasa bile, .NET Framework 1.0 ve 1.1 sürümlerinde halen küçük de olsa kararlı olmayan bir kilitlenme oluşması ihtimali vardır.

Tüm gerekircilik dışılıklar, karışık DLL yükleme işleminden kaldırıldı. Bu, şu değişiklikler ile gerçekleştirilmiştir:

  • CLR, artık karışık DLL'ler yüklerken yanlış varsayımlar yapar.

  • Yönetilen ve yönetilmeyen başlatma iki ayrı ve farklı aşamada gerçekleştirilir. Yönetilmeyen başlatma önce oluşur (DllMain yoluyla) ve yönetilen başlatma, bir .cctor adı verilen .NET destekli bir yapı yoluyla, sonradan oluşur. /Zl ya da /NODEFAULTLIB kullanılmadığı sürece sonuncu belirtilen kullanıcıya tamamen saydamdır. Daha fazla bilgi için bkz. / NODEFAULTLIB (kitaplıklar yoksay) ve /Zl (Varsayılan kitaplık adını gözardı et).

Yükleyici kilidi yine de meydana gelir, ancak bu kez tekrarlanarak meydana gelir ve algılanır. DllMain, MSIL yönergeleri içeriyorsa, derleyici Derleyici uyarı (düzey 1) C4747 uyarısını oluşturur. Ayrıca, CRT veya CLR, MSIL'i yükleyici kilidi altında yürütmek için algılama ve raporlama girişimlerinde bulunacaktır. CRT saptaması çalışma zamanı tanılamasında C Çalışma Zamanı Hatası R6033 görülmesine neden olur.

Bu belgenin geri kalanı, MSIL yükleyicisi kilidi altında yürütülebilinen kalan senaryoları, bu senaryoların her birinin altındaki sorunlara ilişkin çözümleri ve hata ayıklama tekniklerini tanımlar.

Senaryolar ve Geçici Çözümler

Yükleyici kilidi altında kullanıcı kodunun MSIL öğesini yürütebileceği birçok farklı durum vardır. Geliştirici, kullanıcı kod uygulamasının bu şartların her biri altında MSIL yönergelerini yürütmeye çalışmayacağını garanti etmelidir. Aşağıdaki alt bölümler en sık karşılaşılan durumlarda sorunların nasıl çözüleceğine ilişkin bir tartışmanın tüm olasılıklarını açıklar.

  • DllMain

  • Statik Başlatıcılar

  • Başlangıcı Etkileyen Kullanıcı Tarafından Sağlanan İşlevler

  • Özel Yerel Ayarlar

ms173266.collapse_all(tr-tr,VS.110).gifDllMain

DllMain işlevi bir DLL için kullanıcı tanımlı giriş noktasıdır. Kullanıcı aksini belirtmediyse, her bir işlem veya iş parçacığı kapsayan DLL'e eklendiğinde veya çıkartıldığında DllMain öğesi çağırılır. Bu çağırma işlevi yükleyici kilidi kilitliyken meydana gelebileceğinden, MSIL'ye kullanıcının sağladığı DllMain işlevleri derlenmemelidir. Ayrıca, DllMain çağrısı ağacında köklü hiçbir işlev MSIL'de derlenemez. Buradaki sorunları çözmek için DllMain öğesini tanımlayan kod #pragma unmanaged öğesiyle değiştirilmelidir. DllMain öğesinin çağırdığı her işlev için bu hareketin aynısının yapılması gerekir.

Nerede bu gerekir arama işlevleri çağıran başka bağlamlarda için MSIL uygulaması gerektiren bir işlev durumlarda, çoğaltma stratejisi kullanılabilir burada hem bir.net ve aynı işlevi doğal bir sürümü oluşturulur.

Alternatif olarak, DllMain gerekli değilse veya bu yükleyici kilidi altında yürütülmesine gerek duyulmazsa, kullanıcı tarafından sağlanan DllMain uygulaması kaldırılabilir ve böylelikle sorun giderilecektir.

DllMain doğrudan MSIL yürütme girişiminde bulunursa Derleyici uyarı (düzey 1) C4747 sonucu ortaya çıkar. Ancak, derleyici DllMain'in başka bir modülde sırasıyla MSIL yürütmeyi deneyen bir işlevi çağırdığı durumları algılayamaz.

Bu senaryo hakkında daha fazla bilgi edinmek için lütfen "Tanılanacak Aksaklıklar" bölümüne bakın.

ms173266.collapse_all(tr-tr,VS.110).gifStatik Nesneleri Başlatma

Dinamik bir başlatıcı gerekliyse statik nesnelerin başlatılması kilitlenmeyle sonuçlanabilir. Bir statik değişkenin derleme sırasında bilinen bir değere atanması gibi basit durumlar için, hiçbir dinamik başlatılma gerekmez, böylece kilitlenme riski yoktur. Ancak, statik değişkenler tarafından başlatılan işlev çağrıları, oluşturucu çağırmaları ya da derleme zamanında değerlendirilemeyen deyimlerin tümü kodun modül başlatılması sırasında çalıştırılmasını gerektirir.

Aşağıdaki kod, dinamik başlatma gerektiren statik başlatıcı örnekleri gösterir: bir işlev çağrısı, nesne oluşturma ve bir işaretçi başlatma. (Bu örnekler statik değildir, ancak aynı etkiye sahip genel kapsamda tanımlandıkları varsayılır.)

// dynamic initializer function generated
int a = init();
CObject o(arg1, arg2);  
CObject* op = new CObject(arg1, arg2);

Bu kilitlenme riski, içeren modülün /clr öğesiyle derlenmiş olup olmamasına ve MSIL'in yürütülüp yürütülmeyeceğine bağlıdır. Özellikle, statik değişken /clr olmadan derlenmişse (ya da bir # pragma unmanaged bloku içinde bulunuyorsa) ve bunu başlatmak için gerekli olan dinamik başlatıcı MSIL talimatlarının yürütülmesine neden oluyorsa kilitlenme oluşabilir. Bu, /clr olmadan derlenen modüller için statik değişkenlerin başlatılmasının DllMain tarafından gerçekleştirilmesinden kaynaklanır. Buna karşılık, /clr öğesi ile derlenmiş statik değişkenler, yönetilmeyen başlatma aşaması tamamlanıp yükleyici kilidi serbest bırakıldıktan sonra.cctor tarafından başlatılır.

Statik değişkenlerin (sorunu gidermek için gereken süreyi kabaca düzenleyen) dinamik başlangıcından kaynaklanan kilitlenmeye ilişkin birtakım çözümler mevcuttur:

  • Statik değişken içeren kaynak dosya /clr öğesiyle derlenebilir.

  • Sabit değişken tarafından çağrılan tüm işlemler, #pragma unmanaged yönergesi kullanılarak yerel koda derlenebilir.

  • Farklı adlara sahip bir.NET ve yerel sürüm belirterek, statik değişkenin bağlı olduğu kodu el ile kopyalayın. Ardından geliştiriciler yerli versiyonu yerli statik başlatıcılardan ve .NET sürümü başka bir yerden çağırabilir.

ms173266.collapse_all(tr-tr,VS.110).gifBaşlangıcı Etkileyen Kullanıcı Tarafından Sağlanan İşlevler

Başlangıç sırasında başlatma için kitaplıkların bağlı olduğu kullanıcı tarafından sağlanan birkaç işlev mevcuttur. Örneğin, C++ üzerindeki new ve delete gibi işleçler, genel olarak aşırı yüklendiğinde, STL başlatılması ve yok edilmesi dahil, kullanıcı tarafından sağlanan sürümler her yerde kullanılır. Bunun sonucunda, STL ve kullanıcı tarafından sağlanan statik başlatıcıları, bu işleçlerin herhangi bir kullanıcı tarafından sağlanan sürümlerini çağıracaktır.

Kullanıcı tarafından sağlanan sürümler MSIL'e derlenmişse, bu başlatıcılar yükleyici kilidi kilitli durumdayken MSIL talimatlarını yürütmeyi deneyecektir. Kullanıcı tarafından sağlanan mallocun da aynı sonuçları vardır. Bu sorunu gidermek için bu aşırı yüklemelerin veya kullanıcı tarafından sağlanmış tanımların #pragma unmanaged yönergesi kullanılarak yerel kod olarak uygulanması gerekir.

Bu senaryo hakkında daha fazla bilgi edinmek için lütfen "Tanılanacak Aksaklıklar" bölümüne bakın.

ms173266.collapse_all(tr-tr,VS.110).gifÖzel Yerel Ayarlar

Kullanıcı özelleştirilmiş bir genel yerel ayar sağlıyorsa, bu yerel ayar statik olarak başlatılanlar da dahil, gelecekteki bütün G/Ç akışlarını başlatmak için kullanılır. Bu genel yerel nesne MSIL'e derlenmişse, yükleyici kilidi kilitliyken MSIL'e derlenmiş yerel nesne üye işlevleri çağrılabilir.

Bu sorunu çözmek için üç seçenek mevcut:

Tüm genel I/O akışı tanımlarını içeren kaynak dosyaları /clr seçeneği kullanarak derlenebilir. Bu statik başlatıcılarının yükleyici kilidi altında çalıştırılmalarına engel olur.

Özel yerel ayar işlev tanımları #pragma unmanaged yönergesi kullanılarak yerel koda derlenebilir.

Yükleyici kilidi serbest bırakıldıktan sonra özel yerel ayarı genel yerel ayar olarak belirlemekten kaçının. Daha sonra açıkça özel yerel ayarlarla başlatma sırasında oluşturulan Giriş/Çıkış akışlarını yapılandırın.

Tanılanacak Aksaklıklar

Bazı durumlarda kilitlenmelerin kaynağını tespit etmek zordur. Aşağıdaki alt bölümler bu senaryoları ve bu sorunları çözmenin yollarını tartışır.

ms173266.collapse_all(tr-tr,VS.110).gifÜstbilgilerde Uygulama

Seçili durumlarda, başlık dosyalarının içindeki işlev uygulamaları tanıyı karmaşıklaştırabilir. Satır içi işlevlerin ve şablon kodunun her ikisinin de bir üstbilgi dosyasında belirtilmesi gerekir. C++ dili, aynı ada sahip işlevlerin bütün uygulamalarında anlam açısından eşdeğer olmaya zorlayan Tek Tanım Kuralı'nı belirtir. Sonuç olarak, verilen işlevin çift uygulamasına sahip nesne dosyaları birleştirilirken C++ bağlayıcının herhangi bir özel durum otaya koymasına gerek yoktur.

Visual C++, .NET ve Visual C++.NET 2003'te farklı en iyileştirme seçenekleri farklı kaynak dosyaları için kullanıldığında ileri bildirimlere eşlik etmesi için bağlayıcı mantıksal olarak eşit olan bu tanımların en büyüğünü seçer. Bu karışık yerel ağ için bir sorun oluşturur/.NET DLLs.

Aynı başlık hem /clr öğesinin etkin olduğu, hem de devre dışı olduğu CPP dosyaları tarafından dahil edilebildiği için, veya bir #pragma unmanaged bloğunun içine #dahil edilebildiği için, başlıklarda uygulamalar sağlayan fonksiyonların hem MSIL, hem de yerli sürümlerine sahip olmak mümkündür. MSIL ve yerli uygulamalar, yükleyici kilidi altında başlatma bakımından, bir tanım kuralını etkili bir şekilde ihlal eden farklı semantiklere sahiptir. Sonuç olarak, bağlayıcı en büyük uygulamayı seçtiğinde, açıkça başka bir yerde #pragma yönetilmeyen yönergesi kullanılarak yerel kod derlenmiş olsa bile, bir işlevin MSIL sürümünü seçebilir. Bir şablonun MSIL sürümünün veya satır içi işlemin yükleyici kilidi altında asla çağırılmamasını sağlamak için yükleyici kilidi altındaki her böyle işlemin her tanımının #pragma unmanaged yönergesiyle değiştirilmiş olması gerekir. Üstbilgi dosyası üçüncü taraftan ise, bunu sağlamanın en kolay yolu soruna yol açan üstbilgi dosyası için #pragma yönetilmeyen yönergesini #include yönergesinin etrafında itme ve açmadır. (Bir örnek için bkz. managed, unmanaged.) Ancak, bu strateji .NET API'ları araması gereken diğer kod içeren üstbilgiler için çalışmaz.

Yükleyici kilidi ile ilgilenen kullanıcılara bir kolaylık olarak, bağlayıcı bir tercih sunulduğunda yönetilen uygulama yerine yerel uygulamayı seçecektir. Bu yukarıdaki sorunları önler. Ancak, derleyici ile çözülmemiş iki sorun nedeniyle bu sürümde bu kuralın iki istisnası vardır:

  • Satır içi bir işleve yapılan çağrı genel statik bir işlev işaretçisi aracılığıyladır. Bu senaryo özellikle önemlidir, çünkü sanal işlevler genel işlev işaretçileri ile çağrılır. Örnek:
#include "definesmyObject.h"
#include "definesclassC.h"

typedef void (*function_pointer_t)();

function_pointer_t myObject_p = &myObject;

#pragma unmanaged
void DuringLoaderlock(C & c)
{
    // Either of these calls could resolve to a managed implementation, 
    // at link-time, even if a native implementation also exists.
    c.VirtualMember();
    myObject_p();
}
  • Itanium hedefli derleme ile tüm işlev işaretçilerinin uygulanması sırasında hata oluşur. Yukarıdaki örnekte, çağrı myObject_p during_loaderlock() içinde yerel olarak tanımlanmış olan, yönetilen bir uygulamasını da çözebilir.

ms173266.collapse_all(tr-tr,VS.110).gifHata Ayıklama Modunda Tanılama

Yükleyici kilit sorunlarının tüm tanıları Hata Ayıklama yapılarıyla yapılmalıdır. Sürüm yapıları tanı oluşturmayabilir ve Serbest Bırakma modunda gerçekleştirilen optimizasyonlar yükleyici kilidi senaryolarında bazı MSIL öğelerini maskeleyebilir.

Yükleyici Kilidi Konusundaki Hatalar Nasıl Ayıklanır

Bir MSIL işlevi çağrıldığında, CLR'nin oluşturduğu tanı CLR'nin yürütmeyi askıya almasına neden olur. Buna karşılık, bu işlemdeki hata ayıklama çalıştırılırken de Visual C++ karma mod hata ayıklayıcının askıya alınmasına neden olur. Ancak, sürece eklenirken, karışık hata ayıklayıcısını kullanarak hata ayıklayıcı için yönetilen yordam dökümü almak mümkün değildir.

Yükleyici kilidi altında çağırılan belirli MSIL işlevini tanımlamak için geliştiricilerin aşağıdaki adımları tamamlaması gerekir:

  1. mscoree.dll ve mscorwks.dll simgelerinin kullanılabilir olduğundan emin olun.

    Bu iki şekilde yapılabilir. Önce, mscoree.dll ve mscorwks.dll PDB'leri simge arama yoluna eklenebilir. Bunu yapmak için simge arama yolu seçenekleri iletisini açın. (Araçlar menüsünden Seçenekler’i tıklatın. Seçenekler iletişim kutusunun sol bölmesinde, Hata Ayıklama düğümünü Açın ve Simgeler'i tıklatın.) Arama listesine mscoree.dll ve mscorwks.dll PDB dosyalarının yolunu ekleyin. Bu PDB'ler %VSINSTALLDIR%\SDK\v2.0\symbols öğesine yüklenir. Tamam düğmesini tıklatın.

    İkinci olarak, mscoree.dll ve mscorwks.dll için PDB'ler Microsoft Symbol Server'dan indirilebilir. Simge sunucusunu yapılandırmak için simge arama yolu seçenekleri iletişim kutusunu açın. (Araçlar menüsünden Seçenekler’i tıklatın. Seçenekler iletişim kutusunun sol bölmesinde, Hata Ayıklama düğümünü Açın ve Simgeler'i tıklatın.) Aşağıdaki arama yolunu arama listesine ekleyin: http://msdl.microsoft.com/download/symbols. Simge sunucusu önbelleği metin kutusuna bir simge önbelleği dizini ekleyin. Tamam düğmesini tıklatın.

  2. Hata ayıklama modunu yalnızca yerel moda ayarlayın.

    Bunu yapmak için çözümdeki başlangıç projesi için Özellikler kılavuzunu açın. Yapılandırma Özellikleri alt ağacı altında Hata Ayıklama Düğümü'nü seçin. Hata Ayıklayıcı Türünü Yalnızca Yerel olarak ayarlayın.

  3. Hata Ayıklayıcı'yı başlatın (F5).

  4. /clr tanısı üretildiğinde Yeniden Dene'yi tıklatın ve ardından Kes'i tıklatın.

  5. Çağrı yığını penceresini açın. (Debug menüsünden Windows'u, ardından da Çağrı Yığını öğesini tıklatın.) Soruna yol açan DllMain veya statik başlatıcı yeşil bir ok ile tanımlanır. Soruna neden olan işlev tanımlanmamışsa, bulmak için aşağıdaki adımlar izlenmelidir.

  6. Komut penceresini (Hata Ayıklama menüsünde, Windows'u ve ardından Komut'u tıklatın) açın.

  7. SOS hata ayıklama hizmetini yüklemek için komut penceresine .load sos.dll yazın.

  8. Dahili /clr yığınının tam bir listesini elde etmek için komut penceresine !dumpstack yazın.

  9. _CorDllMain (soruna DllMain neden oluyorsa) veya _VTableBootstrapThunkInitHelperStub ya da GetTargetForVTableEntry (soruna statik başlatıcı neden oluyorsa) öğesinin birinci örneğini arayın. Bu çağrının hemen altındaki yığın girişi, MSIL çağırma yükleyicisi kilidinin altındaki yürütme girişiminde bulunulan, gerçekleştirilen MSIL işlevinin çağırmasının uygulandığı giriştir.

  10. Kaynak dosyaya ve Adım 9'da belirtilen satır numarasına gidin ve Senaryolar bölümünde açıklanan senaryoları ve çözümleri kullanarak sorunu giderin.

Örnek

ms173266.collapse_all(tr-tr,VS.110).gifTanımlama

Aşağıdaki örnek kodu DllMain'den bir genel nesne oluşturucusuna taşıyarak yükleyici kilidinden nasıl kaçınılacağını gösterir.

Bu örnekte özgün olarak DllMain öğesinde olan yönetilen nesneyi barındıran oluşturucusu olan genel yönetilen bir nesne bulunmaktadır. Bu örneğin ikinci bölümü, başlatmayı yapan modül oluşturucuyu çağırmak için yönetilen nesneye ilişkin bir örnek oluşturarak derlemeye başvurur.

ms173266.collapse_all(tr-tr,VS.110).gifKod

// initializing_mixed_assemblies.cpp
// compile with: /clr /LD 
#pragma once
#include <stdio.h>
#include <windows.h>
struct __declspec(dllexport) A {
   A() {
      System::Console::WriteLine("Module ctor initializing based on global instance of class.\n");
   }

   void Test() {
      printf_s("Test called so linker does not throw away unused object.\n");
   }
};
 
#pragma unmanaged
// Global instance of object
A obj;
 
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
   // Remove all managed code from here and put it in constructor of A.
   return true;
}

Örnek

ms173266.collapse_all(tr-tr,VS.110).gifKod

// initializing_mixed_assemblies_2.cpp
// compile with: /clr initializing_mixed_assemblies.lib
#include <windows.h>
using namespace System;
#include <stdio.h>
#using "initializing_mixed_assemblies.dll"
struct __declspec(dllimport) A {
   void Test();
};

int main() {
   A obj;
   obj.Test();
}

ms173266.collapse_all(tr-tr,VS.110).gifÇıktı

Module ctor initializing based on global instance of class.

Test called so linker does not throw away unused object.

Ayrıca bkz.

Kavramlar

Karışık (Yerel ve Yönetilen) Derlemeler