Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Viestintä ohjelman (C#) ja DLL:n (C++) välillä SendMessagella?

Mazzimo [12.01.2008 19:13:20]

#

Eli tilanne on tämä: Minulla on DLL-kirjasto, joka on tehty C++:lla. Lisäksi minulla on ohjelma, joka on tehty C#:lla (editori). Yritän tehdä sellaista väkerrystä, että kun editorista painetaan nappia, kutsutaan DLL:stä funktiota, joka käynnistää taustasäikeen (tarkoituksena on taustaprosessi, jotta editoria voidaan käyttää prosessin aikana). Taustasäikeen tehtävänä on parsia tekstitiedostoja.

Haluan kuitenkin, että säie ja ohjelma voivat komminikoida keskenään (esim. virhetilanteet säikeessä ilmoitetaan ohjelmalle). Kun esimerkiksi virhetilanne tapahtuu (tiedoston luvuissa havaitaan virhe), lähettää säie SendMessage (tai vastaava) ohjelmalle tiedon siitä.

Seuraavaksi vaiheet selitettyinä yksi kerrallaan ja koodin kanssa.

1) Kun käyttäjä painaa nappia, kutsutaan dll:stä funktiota:

[DllImport("myLib.dll", EntryPoint = "StartThread",
           ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
public static extern void StartThread( [MarshalAs(UnmanagedType.LPStr)] string filename,
IntPtr hwnd );

///////////

private void MyButton_Click(object sender, EventArgs e)
{
     ((Button)sender).Enabled = false;  // vain yksi taustaprosessi kerrallaan
     StartThread( "myfile.txt", this.Handle );  // annetaan kahva kommunikointia varten
}

2) DLL käynnistää säikeen:

// otos dll:n koodista (c++)

// viestin id
#define __MSG_EXIT__ 0xFF321F2

struct Settings
{
	std::string  filename;
	HWND  host_hwnd;		// the handle received from application
};

/** globaalit asetukset! */
Settings* gSettings = 0;




/** tämä on itse säiefunktio */
DWORD WINAPI __internel_ThreadFunc(LPVOID lpParam)
{
	while(1)
	{
	// koodia....
	}


	// LÄHETETÄÄN VIESTI OHJELMALLE SÄIKEEN LOPPUMISESTA!! TÄRKEÄ!!
	SendMessage( gSettings->host_hwnd, __MSG_EXIT__, NULL, NULL );

	// testausta varten
	::MessageBoxA( NULL, "SUCCESS!", "", MB_OK );

	return 0;
}


extern "C" __declspec(dllexport) void StartThread(const char* fname, HWND hwnd)
{
	gSettings = new Settings();
	gSettings->filename = fname;
	gSettings->host_hwnd = hwnd

	// luodaan ja käynnistetään säie
	HANDLE thread = CreateThread( NULL,
		0,
		__internel_ThreadFunc,
		0,
		0,
		NULL);

	if( thread == NULL ) { ExitProcess( 0 ); ::MessageBoxA( NULL, "FAIL!", "", MB_OK ); }
}

3) Tällä tavalla ohjelma käsittelee viestejä:

public partial class MainForm : Form
{
   // ..... koodia .....

   const int __MSG_EXIT__ = 0xFF321F2;


   [System.Security.Permissions.PermissionSet( System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
   protected override void WndProc(ref Message m)
   {
      switch (m.Msg)
      {
          // tarkistetaan lopetusviesti
          case __MSG_EXIT__:
              // ... käsitellään viesti ...
              break;
      }
      base.WndProc(ref m);
   }

}

Noh... Ongelma on sitten tämä: DLL ei lähetä tuota __MSG_EXIT__ viestiä tai ohjelma ei ota sitä vastaan. Olen kuitenkin 100% varma, että säie saavuttaa lähetyskohdan, sillä alla oleva Messuboksi ilmestyy ruudulle ("SUCCESS!"). Silti viestiä ei ohjelmaan ilmaannu.

Olenko tehnyt jotain karmivasti pieleen? Miten ongelman saisi korjattua?
Kiitos etukäteen.

Mazzimo [13.01.2008 10:54:24]

#

Joo-o. Ratkaistu.
Viesti piti rekisteröidä RegisterWindowMessage:lla ennen käyttöä.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta