まず、↓の関数宣言ですが、
int func01(void instance, int argc, char *argv);
いわゆるmain関数的な、↓が正しい形式ですよね?
(※MarkDownの記述で*****がイタリック指定として扱われてしまったのだと思われます)
int func01(void* instance, int argc, char **argv);
その前提で話を進めささせていただきます。
さて、エラー内容はfunc01の第三引数の型変換が不正というものなので、コンパイルに通すだけなら下記のようにすればよいと思います。
code = func01(minst, dat02, (char**)dat01);
ただしこれでは根本的な解決とはいえません。
というのも、func01内部でdat01がどう処理されるかがわからないためです。
まず、const char**(※コード上はconst char * dat01[9])として宣言されたデータは、その内容が読み込み専用として扱われます。
一方でconst無しの**char****として宣言されたデータは、その内容が読み書き可能であるとして扱われます。
ご提示のサンプルの場合、dat01の配列は**"aaa"**などのリテラル(※変数を介さない直値の文字列)を保持するため、**const char****として宣言する必要があります(※リテラルはプログラム領域に保持されるので書きみ不可です)。
ですのでdat01をchar**にキャストしてfunc01に渡してしまうと、その内容を書き換えられてしまう恐れがあり、プログラムを実行した際に予期せぬ結果を招く可能性があります。
func01関数をご自身で実装されているのであれば、その内部で第三引数として渡したdat01への書き込みが行われていないことを確かめ、const char** argvと型を変えるのが望ましいです。
仮に、func01の関数内部でargvの内容を書き換える必要がある場合、もしくはfunc01の実装内容を変更できない場合(外部ライブラリを利用している等)であれば、書き換え可能な形式にしてデータを渡す必要があります。
例えば、下記のように上書きされてもよいように十分なバッファを確保して、dat01へ割当て、そこに文字列をコピーしてから渡します。
char * dat01[9];
// 書き込まれても良いようにバッファの確保と割当
char buf[9][256];
for( int i=0; i<9; i++ ) dat01[i] = buf[i];
sprintf( dat01[0], "" ); // バッファに書き込み
sprintf( dat01[1], "aaa" ); // バッファに書き込み
/* 省略 */
sprintf( dat01[8], "hhhhh" ); // バッファに書き込み
dat02 = 9;
code = func01(minst, dat02, dat01); // dat01の内容は書き換え可能
C++では変数にconstをつけるかつけないかの判断がよく出てきます。
constがついていたらReadOnly、ついていなければWritableと覚えておきましょう。