Sadece Windows'ta meydana gelen ilginç bir sorunla karşı karşıyayım, Linux/Mono'da her şey iyi çalışıyor. C# kodundan P/Invoke ile aradığım MySQL Cluster NDB API kütüphanesi etrafında bir C++ sarmalayıcısı oluşturdum. Şimdiye kadar üç yöntem vardır: kaynak MySQL NDB API AccessViolationException
init()
serbest bırakır kolu
release()
kullanarak veritabanından veri okuyan bir koluread()
çevreyi başlatır ve döner
init()
her kurulumda iyi çalışıyor. Ancak,read()
,AccessViolationException
'u atar, ancak yalnızca Windows'ta ve yalnızcainit()
bir iş parçacığında veread()
diğerinde çağrıldığında oluşur. Her şeyi tek bir iş parçacığında yaparsak işe yarıyor! Olası neden hakkında herhangi bir düşünce takdir edilecektir.Güncelleme 2016/12/04 - aynı davranış
init()
bir iplik diğerinderead()
çağrılır basit C++ test programı ile fark edilmiştir. Bu nedenle, hatanın C#/C++ interop ile hiçbir ilgisi yoktur, bu, here (lib
klasörü,mysqlclient.lib
vendbclient_static.lib
klasörü) indirilebilen NDB API kitaplığı içindeki bir şeydir.C# kodu :
private const string ndbapi = "ndb"; [DllImport(ndbapi)] public extern static IntPtr init(IntPtr conn_string); [DllImport(ndbapi)] public extern static void read(IntPtr ndb_cluster_conn); [DllImport(ndbapi)] public extern static void release(IntPtr ndb_cluster_conn, IntPtr char_arr_ptr); private static IntPtr handle; private static void InitNdb() { unsafe { fixed (byte* conn_buf = Encoding.UTF8.GetBytes("node1:1186")) { handle = ndb_api_init(new IntPtr(conn_buf)); } } } static void Main(string[] args) { Thread t = new Thread(InitNdb);// IF I CALL InitNDB IN THE SAME THREAD, EVERYTHING WORKS t.Start(); .. //waiting for Thread t to complete... IntPtr bytes_read = read(handle); ... }
C++ kodu: (official documentation örneklerle dayanarak): MySQL Cluster posta listesinin yardımıyla
#if defined(WIN32) #define DLLEXPORT __declspec(dllexport) #define CALLCV __stdcall #else #define DLLEXPORT __attribute__((visibility("default"))) #define CALLCV __attribute__((cdecl)) #endif .. extern "C" DLLEXPORT Ndb_cluster_connection* CALLCV init(char* connection_string) { ndb_init(); // Object representing the cluster Ndb_cluster_connection* cluster_connection = new Ndb_cluster_connection(connection_string); if (cluster_connection->connect(3, 2, 1)) { std::cout << "Cluster management server not ready,error:" << cluster_connection->get_latest_error_msg() << "\n"; exit(-1); } if (cluster_connection->wait_until_ready(10, 0) < 0) { std::cout << "Cluster not ready within 10 secs, error:" << cluster_connection->get_latest_error_msg() << std::endl; } return cluster_connection; } extern "C" DLLEXPORT char** CALLCV read(Ndb_cluster_connection* cluster_connection) { Ndb *ndb_obj = new Ndb(cluster_connection, db_name); if (ndb_obj->init()) { std::cout << "Error while initializing Ndb " << std::endl; } const NdbDictionary::Dictionary* dict = ndb_obj->getDictionary(); const NdbDictionary::Table *table = dict->getTable("table_name"); <-- THIS IS THE LINE THAT THROWS ACCESS VIOLATION EXCEPTION .. }
Bunu mu demek istediniz: ndb_api_init' by 'init'? – Ripple
@Ripple Evet, c/p kodu yaparken hata yaptım. Düzenlendi, tnx. –
Ve eğer C# sarmalayıcısını kullanmadan C++ 'da aynı işlemi yaparsanız (yani farklı konuları okuyorsanız), sonuç ne olur? – Evk