0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Inside Wine; WINEDLLPATH

Last updated at Posted at 2018-02-26

[目次] (https://qiita.com/Yutaka_Aoki/items/9d38ea98406f4096435b)

Inside Wine; WINEDLLPATH

WINEDLLPATH の不具合

調べてみると、/wine/libs/wine/loader.c の中の build_dll_path() 関数の中で、環境変数 WINEDLLPATH が、読み取られ、: を 0x00 に変えてから、dll_paths[] 配列に : で区切られたそれぞれの文字列の先頭アドレスを代入している。

しかし、その処理に入る前に、get_dlldir() 関数が NULL 以外を返した場合、dll_paths[0] にその関数が返した文字列のアドレスを入れてしまう。

そして、実際の get_dlldir() は、"/usr/local/bin/../lib/wine" という文字列を返してくるので、そっちのパスの方が、WINEDLLPATH の優先順位よりも上になってしまう。

get_dlldir() は、

~/wine/libs/wine/config.c
/* retrieve the default dll dir */
const char *get_dlldir( const char **default_dlldir )
{
    *default_dlldir = DLLDIR;
    return dlldir;
}

となっているが、DLLDIR は、Makefile の中で、gcc に -D オプションによってコンパイル開始時の #define マクロ として文字列が渡されている。

修正箇所

c:~/wine/libs/wine/loader.c の build_dll_path() 関数を変更する。

make すると、c:~/wine/libs/wine/libwine.so.1.0

が作成される。

これを、自分のアプリの場合にだけは使われるようにする。

旧関数

~/wine/libs/wine/loader.c
/* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void)
{
	int len, count = 0;
	char *p, *path = getenv( "WINEDLLPATH" );
	const char *dlldir = get_dlldir( &default_dlldir );

	if (path)
	{
		/* count how many path elements we need */
		path = strdup(path);
		p = path;
		while (*p)
		{
			while (*p == ':') p++;
			if (!*p) break;
			count++;
			while (*p && *p != ':') p++;
		}
	}

	dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
	nb_dll_paths = 0;

	if (dlldir)
	{
		dll_path_maxlen = strlen(dlldir);
		dll_paths[nb_dll_paths++] = dlldir;
	}
	else if ((build_dir = wine_get_build_dir()))
	{
		dll_path_maxlen = strlen(build_dir) + sizeof("/programs");
	}

	if (count)
	{
		p = path;
		while (*p)
		{
			while (*p == ':') *p++ = 0;
			if (!*p) break;
			dll_paths[nb_dll_paths] = p;
			while (*p && *p != ':') p++;
			if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
				dll_path_maxlen = p - dll_paths[nb_dll_paths];
			nb_dll_paths++;
		}
	}

	/* append default dll dir (if not empty) to path */
	if ((len = strlen(default_dlldir)) > 0)
	{
		if (len > dll_path_maxlen) dll_path_maxlen = len;
		dll_paths[nb_dll_paths++] = default_dlldir;
	}
}

新関数

~/wine/libs/wine/loader.c
/* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void)
{
	int len, count = 0;
	char *p, *path = getenv( "WINEDLLPATH" );
	const char *dlldir = get_dlldir( &default_dlldir );
	
	if (path)
	{
		/* count how many path elements we need */
		path = strdup(path);
		p = path;
		while (*p)
		{
			while (*p == ':') p++;
			if (!*p) break;
			count++;
			while (*p && *p != ':') p++;
		}
	}

	dll_paths = malloc( (count+2) * sizeof(*dll_paths) );
	nb_dll_paths = 0;
	
	dll_path_maxlen		= 0;
	
	if (count)
	{
		p = path;
		while (*p)
		{
			while (*p == ':') *p++ = 0;
			if (!*p) break;
			dll_paths[nb_dll_paths] = p;
			while (*p && *p != ':') p++;
			if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
				dll_path_maxlen = p - dll_paths[nb_dll_paths];
			nb_dll_paths++;
		}
	}
	
	if (dlldir) {
		int		len		= strlen(dlldir);
		if ( len > dll_path_maxlen ) {
			dll_path_maxlen		= len;
		}
		dll_paths[nb_dll_paths++] = dlldir;
	}
	else if ((build_dir = wine_get_build_dir())) {
		int		len		= strlen(build_dir) + sizeof("/programs");
		if ( len > dll_path_maxlen ) {
			dll_path_maxlen		= len;
		}
	}
	
	/* append default dll dir (if not empty) to path */
	if ((len = strlen(default_dlldir)) > 0) {
		if (len > dll_path_maxlen) {
			dll_path_maxlen		= len;
		}
		dll_paths[nb_dll_paths++]	= default_dlldir;
	}
	
	#if 1
	int		cnt;
	for ( cnt = 0; cnt < nb_dll_paths; cnt++ ) {
		fprintf( stderr, "%d: %s\n", cnt, dll_paths[cnt] );
	}
	#endif
}

以下のようなスクリプトを作っておく。

自分のアプリを実行する前に、

$ . myenv

として、先頭に 「.」を付けて環境変数が設定されるようにする。

export LD_LIBRARY_PATH=.

によって、カレント・ディレクトリにある、libwine.so.1

が探されるようになる。

$ ln -s /media/Yyyy/my_winedev/wine/libs/wine/libwine.so.1.0 libwine.so.1

などとして、カレント・ディレクトリに本体へのリンクを作っておく。

パスに付いては、詳細は省略する。以下のスクリプトは自分の場合。

WINEDLLPATH の設定の仕方は、ソースを検索すると、英語だが、自然言語で書かれているので読む。

myenv
#!/bin/sh

#
# $ . myenv [ret]
#
# として読みこます事。冒頭の「. 」(ドットと空白) が重要
#

PATH=/media/Yyyy/my_winedev/bin2/bin:$PATH

DLL=/media/Yyyy/my_winedev/wine/dlls

WINEDLLPATH=$DLL/winex11.drv
WINEDLLPATH+=:$DLL/gdi32
WINEDLLPATH+=:$DLL/user32
WINEDLLPATH+=:/media/Yyyy/my_winedev/bin2/lib/wine

export WINEDLLPATH

export WINESERVER=/media/Yyyy/my_winedev/wine/server/wineserver

export LD_LIBRARY_PATH=.
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?